small
799B · 28 linestokens emitted: Prism 256 · sugar-high 325 · twinkleplop 609 · Shiki (wasm) 216 · Shiki (JS engine) 216
How fast does twinkleplop turn source into tokens, and into HTML, compared to the other JavaScript syntax highlighters? Every bar in a chart was measured in the same process, alternating between libraries, so the machine drifting mid-run moves all of them together instead of flattering whichever one happened to go first.
Source in, structured token stream out. No HTML, no rendering — just the parse.
Every language at roughly 1KB, 10KB and 100KB. The small tier is the docs-snippet case, where fixed per-call cost still dominates; the large tier is a big vendored file. These are inputs we assembled, so read them alongside the set below.
tokens emitted: Prism 256 · sugar-high 325 · twinkleplop 609 · Shiki (wasm) 216 · Shiki (JS engine) 216
tokens emitted: twinkleplop 5325 · sugar-high 3269 · Prism 2542 · Shiki (wasm) 2176 · Shiki (JS engine) 2176
tokens emitted: twinkleplop 41688 · sugar-high 25162 · Prism 19298 · Shiki (wasm) 15424 · Shiki (JS engine) 15424
The sample files from shikijs/textmate-grammars-themes, vendored and pinned. Shiki's own engine benchmark runs on these. We did not choose them, which is the point: a highlighter benchmark published by the people who wrote the highlighter is worth exactly as much as its inputs. shikijs/textmate-grammars-themes at 45e292ef.
tokens emitted: twinkleplop 957 · sugar-high 580 · Prism 438 · Shiki (wasm) 387 · Shiki (JS engine) 387
Token counts are the caveat on every bar. A library that emits half as many tokens for the same file is doing less work per byte, not the same work faster. The counts are printed under each chart so you can see which is which rather than taking the bar on trust.
The HTML numbers are not measuring identical output. twinkleplop and Prism emit classes and leave colour to a stylesheet; Shiki resolves a theme and writes inline styles. That is strictly more string work, and it is a real difference in what you get, not a handicap we imposed.
These numbers do not travel. They describe one machine on one day. Comparing a bar here against a number from somewhere else — another run, another runner, another node version — is not a comparison. Within a single chart, the interleaving makes them fair.
⚠️ The machine drifted 6.8% during this run. The ratios still hold; the absolute ops/s figures should be treated as approximate.