Skip to content
Tsumugu

Performance#

What is measured, and why#

Tsumugu measures the time from a save to a rebuilt page. The benchmark tracks the initial build, an unchanged rebuild, and a one-document rebuild:

MeasurementWhy it matters
first buildhow long tsumugu dev takes to answer at all
rebuild, nothing changedthe floor: what a save costs when nothing needs redoing
rebuild, one documentwhat a save actually costs

The search index and exports are also measured because they are cheap to measure, not because it is close to mattering.

Running it#

pnpm run bench           # 200 documents
pnpm run bench 1000      # a larger project

The fixture is generated: documents with front matter, headings, a code block, a table and a link to another document, spread over ten directories. That shape is deliberate. A thousand empty files would measure the file system rather than the pipeline.

Baselines#

Measured on one machine (Apple Silicon, Node 26) with the official preset, including syntax highlighting. Treat them as orders of magnitude, not as a contract: another machine will differ by a factor, and that is fine. What is not fine is a factor appearing between two commits on the same machine.

DocumentsFirst buildRebuild, nothing changedRebuild, one document
200~490 ms~20 ms~20 ms
1000~3.9 s~200 ms~140 ms

Roughly 4 ms per document for the first build, most of it parsing and highlighting. Rebuilds are dominated by the scan, which is one stat per file.

What makes a rebuild cheap#

Tsumugu uses three caches with explicit invalidation keys:

  • The loaded document, invalidated by size and modification time. An unchanged file is not read.

  • The themed body and the outline, invalidated by the content hash. An unchanged document is not parsed, transformed or themed again.

  • The serialized page, invalidated by a signature over everything outside the document that its page depends on: the navigation, the site name, and the page's own diagnostics.

That last one is why editing one document in a thousand-page project costs milliseconds rather than seconds. Before it existed, every page was serialized again on every save because every page carries the navigation. At 2.8 seconds per keystroke-and-save at a thousand documents. The benchmark is what found it.

Guardrail#

tests/performance.test.ts builds a small project and fails if a rebuild that changes nothing is not substantially cheaper than the first build. The threshold is deliberately loose: a test that asserts milliseconds on shared CI hardware fails for reasons that have nothing to do with the change under review. It catches the shape of a regression, such as rebuilds no longer being incremental, rather than its size.

Real numbers come from pnpm run bench, run by a person, on a machine they can name.