Skip to content

Performance — measured, budgeted, reproducible

Measured 2026-07-05 on the 10MB torture document (527,671 lines — the full golden corpus repeated to 10MB: headings, tables, code, footnotes, CJK, deep nesting). Reproduce: npx tsx testing/benchmarks/src/bench.ts.

OperationMeasuredBudget (CI-enforced)
Typing latency, state.apply p95 @10MB< 0.01ms16ms
Serialize 10MB document to markdown2.2s5s
Parse (open) 10MB markdown18.8s25s
Parse 100KB (a huge README)~90ms
Parse 1MB~1.0s

The interesting engineering story

Markdown parsers that resolve emphasis/links over a whole-document token buffer (micromark’s architecture — the price of its exactness) scale superlinearly: our first measurement of the 10MB document was 361 seconds. Editors usually “solve” this by capping document size or using a sloppier parser.

Inkroom instead parses large documents in chunks cut at provably safe block boundaries — a scanner tracks code fences, all five multi-line HTML block types and front matter, so a cut can never land inside a construct; document-global constructs (link reference definitions, footnotes) are shared across chunks and deduplicated after the merge. Each piece stays in the parser’s fast region: 361s → 18.8s, and equivalence with the single-shot parse is enforced by tests, not asserted in a comment (packages/markdown/src/chunk.test.ts).

Typing was never the problem: ProseMirror transactions are O(change), not O(document) — at ten megabytes, applying a keystroke to the document model costs microseconds, and the view only re-renders the touched DOM.

What the budgets mean in practice

  • A 10MB file is ~40× War and Peace in markdown. Real documents (README, wiki page, spec, book chapter) open in tens of milliseconds.
  • The keystroke budget (16ms = one 60fps frame) is spent almost entirely in the browser’s paint, not in Inkroom.
  • The markdown source mode disables its syntax highlighting above 20,000 lines to protect the frame budget (a viewport-scoped highlighter lifts this limit in a minor release).