benchmark #
fuz_code is optimized for runtime syntax styling. This page summarizes how it compares with Prism and Shiki, measures its two renderers in the browser, and lists the benchmarks that run from a checkout. The comparisons come from syntax-highlighter-bench, a separate suite that times each library on the same neutral inputs.
Shiki targets build-time use and runs the Oniguruma regexp engine that TextMate grammars require, trading runtime speed for grammar and theme coverage. fuz_code trades that coverage for a small, fast runtime path. For static content, the svelte_preprocess_fuz_code preprocessor renders at build time. Languages it lacks can be added by writing a lexer.
Compared to Shiki and Prism #
syntax-highlighter-bench measures fuz_code against Prism, Shiki (both its JavaScript and Oniguruma engines), and Twinkleplop, each in its own process, on real code none of them authored. Highlighting to HTML, fuz_code runs about an order of magnitude faster than Prism and one to two orders of magnitude faster than Shiki:
| language | fuz_code vs Prism | fuz_code vs Shiki |
|---|---|---|
ts | ~12x | ~91x |
js | ~8.7x | ~103x |
css | ~6.6x | ~59x |
html | ~6.7x | ~57x |
json | ~6.0x | ~33x |
svelte | ~8.0x | ~123x |
md | ~13x | ~25x |
sh | ~16x | ~73x |
rust | ~6.0x | ~46x |
Run of 2026-10-12 at commit 340492a: fuz_code 0.52.1, Prism 1.30.0, Shiki 4.5.0, Node 24.14.1, AMD Ryzen 5 PRO 7530U.
In the browser #
The in-browser benchmark measures real DOM rendering rather than pure compute. It times fuz_code's two renderers — the standard HTML path (Code) and the experimental CSS Custom Highlight API path (CodeHighlight, ranges) — across the sample languages, reporting mean, median, percentiles, coefficient of variation, and throughput, and it pauses longer between samples when the system looks unstable.
Set the iteration count, warmup runs, cooldown, and content multiplier, then run it on your
own hardware. For the steadiest numbers, launch Chromium with garbage collection exposed
(chromium --js-flags="--expose-gc") so the harness can run a minor collection
between samples.
A sample run of work time — stylize plus DOM commit — per language for each renderer. The
default Code path builds a .token_* span per token;
the experimental CodeHighlight path skips that DOM, so it commits
less:
Run of 2026-07-11, before the tool added Rust.
On your machine #
The command-line benchmarks run from a checkout of the repo:
npm run benchmark— the internal suite, timing every sample at normal and 100× sizes against a local baseline for regression detection.npm run benchmark:cost— the cost model for iterating on a lexer: per-construct costs and each language's time over a grammar-free floor lexer, in a few seconds.
The internal suite includes a pathological group of adversarial inputs (deeply
nested and degenerate source) that tracks the lexer's worst-case cost; the same generators
back the linearity tests.
Design #
- Lexers scan char codes and use native
indexOfand keyword maps in place of regular expressions. - One single-pass lexer per language emitting a flat
Int32Arrayevent stream, rendered to HTML in a single forward pass. - Delimiter scans are amortized linear, with no grammar interpreter or backtracking. A test suite checks that lexing time stays near-linear on adversarial inputs.
- The lexers and styler import nothing outside the package.
The engine keeps no resumable state, so it re-lexes the whole document on every change rather than tokenizing incrementally. In the committed results the largest inputs, up to a few hundred kilobytes of source, take under about ten milliseconds in Node.
See usage for the API and samples for output in every language.