Framework bench: VDOM vs Vapor

Product matrices (storms, FCP): Unified Benchmark Matrix. This page is the Vue framework slice — instrumented BG/e2e, traffic, bundle cost — plus an interactive playground. ReactLynx is a reference baseline, not the subject under test.

Same Vue app in both modes, full dual-thread pipeline (Vue core benchmark ported to Lynx). Select = point update; Update = batch update.

Try it

Tap the same buttons the harness clicks. Badge = tap → DOM settled. Compare Vue Vapor / Vue VDOM; ReactLynx (memo) is there as a reference so you can feel the order of magnitude — not as a ReactLynx product bench (that lives in the unified matrix).

tap a button to measure
Loading Lynx runtime…

What to try: Create 10k → Select storm (point) → Update storm (batch).

Instrumented BG / e2e

Operationkindvdom bgvapor bgbgvdom e2evapor e2ee2e
select rowpoint2.95 ms0.30 ms9.8×3.45 ms0.55 ms6.3×
update every 10thbatch3.20 ms0.55 ms5.8×4.85 ms2.30 ms2.1×
swap rowspoint-ish3.90 ms0.65 ms6.0×4.65 ms1.20 ms3.9×
remove rowpoint2.85 ms0.40 ms7.1×3.40 ms0.90 ms3.8×

e2e < bg because both modes emit near-identical ops — the delta is Vue work on the background thread (shared with your app logic).

Creation e2e is ~parity (vapor create1k ~0.87× … create10k ~0.94×). See vapor mode for REGISTER_TREE / CLONE_TREE.

Cross-thread traffic (create 1k)

vdomvapor
ops per flush17,0007,000 (−59%)
JSON bytes327 KB160 KB (−51%)

On Lynx for Web this barely moves e2e (DOM construction dominates). On native the payload crosses a serialization boundary — halving it matters more there.

Startup, memory, bundle

Metricvdomvapornote
First screen (attach → content)121.7 ms125.8 ms+3%, CIs overlap
Bundle gzip (main.lynx.bundle)39.2 KB49.3 KB+26%
JS heap after 10k rows76–136 MB76–105 MBindicative only

Reproduce

pnpm --filter vue-lynx-benchmark bench          # instrumented
pnpm --filter vue-lynx-benchmark bench:cross    # black-box (+ React ref)
pnpm --filter vue-lynx-benchmark bench:storms

Raw: packages/benchmark/results/.