-
Notifications
You must be signed in to change notification settings - Fork 1
RayoMD tester.md Warm Benchmark 2026 07 17
Commit 49d35a2
reduced the warm native generation median for tester.md on WSL /mnt/e
from 16.13 ms to 7.89 ms. Every candidate round was below the 10 ms goal.
The current Windows build measured 1.21 ms median.
This is a focused before/after optimization record, not an end-to-end export number or a cross-engine ranking.
- Baseline: RayoMD
2.4.0, commit315b404. - Candidate: commit
49d35a2. - Fixture: repository
tester.md, 3,896 bytes and 142 lines, using the Unicode embedded-font path and producing six pages. It exercises headings, inline styles, tables, lists, links, local/remote/missing images, math, and code. The same local mascot source occurs as a direct image, a reference image, and an inline reference image. - Renderer options:
modern normal. - Host: Windows 11 Pro build 26200, AMD Ryzen 5 5600X, 128 GiB RAM.
- Windows build: MinGW-w64 GCC 15.2.0 Release; 1,000 timed builds per process.
- Linux build: WSL2 Ubuntu GCC 13.3.0 Release; 200 timed builds per process;
source, fixture, and output on the Windows-backed
/mnt/emount.
RayoMD --bench reads the Markdown before timing, performs an untimed warm-up
and sample build, then measures repeated in-memory BuildPdf calls. It excludes
process startup, source-file reading, and timed output-file writing. See the
--bench implementation.
| Platform/storage | Sampling | Baseline median (range) | Candidate median (range) | Median change |
|---|---|---|---|---|
Linux WSL /mnt/e
|
5 interleaved rounds x 200 |
16.13 ms (14.89-18.83) |
7.89 ms (7.30-9.40) |
-51.1% |
| Windows workspace | baseline 9 x 1,000; candidate 5 x 1,000 |
1.26 ms (1.17-1.60) |
1.21 ms (1.07-1.42) |
-4.0% nominal |
Linux round averages in run order:
- Baseline:
14.89,18.83,16.41,16.13,15.05ms. - Candidate:
9.14,9.40,7.89,7.30,7.88ms.
The Linux mean moved from 16.262 ms to 8.322 ms, a 48.8% reduction. All
five candidate runs beat 10 ms. The small Windows movement is within the range
where host variation can dominate, so it is treated as neutral; Windows already
beat the target comfortably.
ImageRegistry now records a raw-source alias only after that source has passed
the existing image policy and loaded successfully. When direct and reference
syntax resolve to the same source string later in the same PDF build, the
registry reuses the accepted image instead of repeating path policy resolution
and weakly_canonical filesystem work. That repeated filesystem work was
especially costly on WSL DrvFS.
The change is deliberately local and does not add a global or cross-document cache.
For a local source, the first use still canonicalizes and enforces the existing local-image policy; URL sources still follow the existing fetch policy. On a decoded-cache miss, the source is read or fetched and decoded. Failed or rejected sources never receive an alias, and the registry exists only for one PDF build. A later exact-source match can reuse only image bytes already accepted by that registry; it cannot authorize or read a new path. If a symlink changes during a single build, reuse keeps the initially accepted bytes rather than reopening a new target.
Candidate PDFs were byte-identical to the matching baseline on each platform:
| Platform | Average PDF bytes | Baseline and candidate SHA-256 |
|---|---|---|
| Linux | 494,837 |
89E94517FE9CD99DC29CED66E299076874CEE39FBB4E0614A9FFC2AF49CEA5C4 |
| Windows | 379,528 |
67B5D19D092D910B573C954018B5B238248C6AC0DCC7FE0F4DD4067DBE9AE400 |
The hashes differ across platforms because their embedded font resources
differ; equivalence is baseline versus candidate on the same platform.
Packaged binary sizes were unchanged: 428,592 bytes on Linux and 2,806,784
bytes on Windows.
Order-balanced Windows image-free guardrails, seven rounds x 1,000:
| Fixture | Baseline median | Candidate median |
|---|---|---|
| 24 KiB table | 0.97 ms |
0.85 ms |
| 24 KiB Unicode | 1.67 ms |
1.65 ms |
Both Windows and Linux candidate trees passed all CTest entries (2/2), and
git diff --check was clean.
The quoted Glu transcript reported Build done at 13.033333 ms and total
runtime at 13.557416 ms for barcodes.md. RayoMD's 7.89 ms median is
numerically lower than that Build done value, but it is not an apples-to-apples
head-to-head benchmark:
- Glu's example
barcodes.mdis 490 bytes, 24 lines, and one page with custom barcode elements; RayoMD'stester.mdis 3,896 bytes, 142 lines, and exercises a different feature mix. - Glu's internal build timer covers its input read, Markdown dispatch, HTML/Lua, typesetting, font, PDF, and auxiliary-file pipeline, but not process startup.
- RayoMD's warm
--benchnumber excludes input reading and timed output writing and averages many PDF builds in one process. - The quoted Glu run was not collected as an interleaved same-host A/B against RayoMD.
Relevant sources: Glu timing flow,
Glu Markdown pipeline,
and the barcodes.md fixture.
The defensible statement is that RayoMD beat the requested 10 ms target and its
measured warm number is below the quoted Glu number; it is not a general claim
that one renderer is faster for equivalent work.
Build the exact candidate revision, then run several fresh benchmark processes:
git checkout 49d35a2
cmake -S . -B build/linux -DCMAKE_BUILD_TYPE=Release
cmake --build build/linux --config Release
build/linux/rayomd --bench tester.md benchmark-output/tester-warm/run-1 200 modern normalWindows:
git checkout 49d35a2
cmake -S . -B build/windows -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build build/windows --config Release
build/windows/rayomd.exe --bench tester.md benchmark-output/tester-warm/run-1 1000 modern normalEach command reports one process-level avg_ms. Repeat it in new processes and
use the median. For a before/after check, build 315b404 and 49d35a2 with the
same compiler, flags, filesystem location, renderer options, and iteration
count, then interleave their runs.