Skip to content

Performance goals

Latency targets for Merlon Docs compile and check, and the shard count each target is defined at.

Merlon Docs is designed for full programs (hundreds of shards across multiple guides with dense cross-links) while keeping interactive agent loops and CI gates fast. This page sets the targets. Measurements against them are research records, dated and kept as measured.

Actor Hot path Expectation
LLM doc author edit shard → check Compile+check under a few seconds during authoring
CI merlon check --require-lint PR gate completes before reviewer context switches
Agent (context consumer) Host search → single-shard read No Merlon Docs target, because this path doesn’t run Merlon Docs

The usage model prefers granular context (one shard at a time). Performance work keeps that model viable as repos grow.

The targets below are advisory (Enforceable rules): no gate fails on them. CI doesn’t run the benchmark, and the status column that pnpm bench:dogfood writes records met or miss for the three targets it measures without failing the run. Whoever runs it reads that column against the shard count each target is defined at. The evidence is the dated CSV the run writes beside the research records, and a research record for a run kept as a reference. A smaller corpus that meets a target doesn’t show the target is met at that count. The most recent measured run is Benchmark: this repository’s docs before and after single-pass compile.

Tier 1: Interactive (agent authoring loop)

Section titled “Tier 1: Interactive (agent authoring loop)”
Operation Target Rationale
compile (full repo) < 2 s @ 200 shards An author recompiles after each edit

Tier 2: CI gate (core Merlon Docs only, no peers)

Section titled “Tier 2: CI gate (core Merlon Docs only, no peers)”
Operation Target Rationale
check (core stages) < 5 s @ 200 shards PR feedback under 10 s total
Same < 15 s @ 500 shards Large program still acceptable in CI

The core stages are orphans, compile, refs, built-in links and coverage, the Check gate stages that don’t run a peer linter. The target leaves out the paths stage, which is off by default.

Operation Target Rationale
check --require-lint --require-vale < 30 s @ 200 shards Peers are opt-in; budget separately
Same < 60 s @ 500 shards Upper bound before parallelization / caching

pnpm bench:dogfood runs the benchmark, as Benchmarks describes. Its ms/link row is the link lint time divided by a fixed 357, the compiled link count of the 64-shard corpus in the June 2026 benchmark record. So the row follows total lint time, and it rises as the docs gain links. Its status column compares the row with the 8 ms/link baseline from before single-pass compile. The benchmark records the compile time but not the corpus’s shard count. Its slo_shards column is the count each target is defined at. Work out ms/shard by hand from the compile time and a shard count, and apply the 20% rule to two such figures. CI doesn’t run the benchmark. A regression shows up only when someone runs it by hand.

Metric Target
ms/shard (compile) Trend down; a regression over 20% is a miss
ms/link row (lint time ÷ 357) Trend down between runs at a similar link count
File reads / shard → 1
Compile invocations per check → 1

For the last two rows the benchmark writes a fixed 1, so it doesn’t measure them, and no test checks them.

A guide in the monolith is assembled once for its compiled guide and once for the monolith, because paths and section slugs differ between the two files. Shard reads stay at one per shard. The second assembly can push ms/shard past the 20% limit in the table above, and the double assembly is an accepted exception to that limit.

Link lint reads the monolith as a document of its own, so it checks each link of a guide in the monolith in both files. That second check adds work for each link. Link lint builds the set of heading slugs of each output once, and on Merlon Docs’ own docs that saves more time than the second check costs. Where the second check raises the ms/link row, the rise is accepted.