benchmark #

fuz_code is optimized for runtime syntax styling. This page compares it with Prism and Shiki, measures its two renderers in the browser, and lists the benchmarks that run from a checkout.

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
#

The cross-implementation benchmark measures fuz_code against Prism and Shiki (both the JavaScript and Oniguruma engines). For end-to-end stylize (lexing plus HTML generation), fuz_code runs roughly an order of magnitude faster than Prism and about two orders of magnitude faster than Shiki:

languagefuz_code vs Prismfuz_code vs Shiki
ts~18×~140×
css~8×~90×
html~11×~80×
json~17×~95×
svelte~14×~165×

Representative stylize results on larger inputs from one machine; absolute numbers vary by hardware. See the committed comparison results for the full matrix across engines and sizes, plus tokenize-only rows that compare the raw lexers without HTML generation.

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, with system-stability gating between samples.

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 settle the heap 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:

Code (html) CodeHighlight (ranges)
91 ms 1.00x
12 ms 7.58x
11 ms 1.00x
3 ms 3.67x
28 ms 1.00x
4 ms 7.00x
11 ms 1.00x
2 ms 5.50x
91 ms 1.00x
13 ms 7.00x
69 ms 1.00x
10 ms 6.90x
49 ms 1.00x
8 ms 6.13x

Lower is better. Each language's ratios are relative to its highlighted row, and a negative ratio means that many times slower; hover the other row to compare against it. Ratios come from the rounded times shown, and this run does not include Rust. The benchmark uses complex samples at the tool's default size, so this is illustrative, not representative of most inputs. The live tool also reports paint-settle time, percentiles, and throughput.

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:vs — compares against Prism and Shiki and produces the results above.

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
#

  • No regular expressions — char-code scanning, native indexOf, keyword maps.
  • One single-pass lexer per language emitting a flat Int32Array event stream, rendered to HTML in a single forward pass.
  • No grammar interpreter and no regex backtracking; delimiter scans are amortized linear. A test suite checks that lexing time stays near-linear on adversarial inputs.
  • No dependencies in the lexers or styler — they 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.

See usage for the API and samples for output in every language.