12. Performance budgets
Every number below is a budget on the reference machine: a 2023 mid-range laptop with 4 performance cores, 16 GB of RAM, an integrated GPU and a 1440p display, running the current VS Code.
Every number below is a budget on the reference machine: a 2023 mid-range laptop with 4 performance cores,
16 GB of RAM, an integrated GPU and a 1440p display, running the current VS Code. The fixtures are the
generated files in test/fixtures/bench/ (5 000, 10 000 and 50 000 nodes), so NFR-1, CAN-11 and CMD-31 are
measured against one document each, not against three descriptions of one.
| Budget | Target | Source | Measured by |
|---|---|---|---|
| Open a file | 50 000 nodes in the file, 10 000 on the first page: first frame drawn < 2 s | NFR-1 | test/bench/open.bench.ts: host fold + index + layout in Node; plus the dev page’s performance.mark from init to first tile |
| Re-show after hide | a hidden tab of the 50 000-node file shown again: first tile < 500 ms, viewport and tool state restored exactly | NFR-1, ADR-10 | dev page: hide, show, performance.mark from the init that follows to the first tile; state compared before and after |
| Pan and zoom | 60 fps (p95 frame < 16.7 ms) on a 10 000-node, 200-image page | NFR-1, CAN-11 | dev page in headless Chromium driven by test/bench/canvas.bench.ts: scripted pan and zoom, frame times from requestAnimationFrame |
| Drag 500 nodes | 60 fps | CAN-11 | same, scripted drag |
| Single-node edit | < 16 ms of webview main-thread time from runCommand to the message that hands the worker the patch; the redrawn tile within the next frame |
NFR-1 | performance.measure around predict + fold; worker frame time from its own marks |
| Read tool through the bridge | < 150 ms on the 5 000-node fixture | CMD-31 | test/bench/cli.bench.ts: spawns ud get_metadata against the dev server’s bridge, wall time |
| Read tool headless | < 400 ms on the 5 000-node fixture | CMD-31 | same, no editor; includes Node start-up of the bundled CLI, read and fold (ADR-9) |
| One mutation | < 250 ms (bridge and headless) | CMD-31 | ud run node.update … |
use_figma start-up |
< 50 ms in the process that runs the script, to the first script statement (§8.1) | CMD-31 | a marker statement in the bench script; the script worker, or ud mcp, timestamps it. One-shot headless is excluded |
| Memory, host | extension host plus its script workers ≤ 1.5 GB with the 50 000-node file open and one script run | NFR-10 | process.memoryUsage().rss of the host and resourceLimits of the workers, sampled after the open bench and after a script |
| Memory, webview | ≤ 1 GB per webview with the 50 000-node file (replica, worker replica, tile cache at its 256 MB default, glyph caches) | NFR-10 | Chromium’s performance.measureUserAgentSpecificMemory() on the dev page |
| Raster output | a render above 8 192 × 8 192 px is tiled (§7.2); peak pixmap ≤ 256 MB whatever the requested size | NFR-10 | test/bench/render.bench.ts: ud render --scale 4 of the largest fixture frame, RSS sampled |
| Package size | the .vsix ≤ 25 MB |
NFR-11 | scripts/check-vsix-size.mjs after vsce package in CI; fails the build over the limit |
| File size | 10 000 nodes < 15 MB after consolidation | NFR-3 | test/bench/size.test.ts on the generated fixture |
Fixtures are generated, not committed: test/fixtures/bench/gen.ts builds the three files from a seed
(screens of cards, lists, text, instances and images) into test/fixtures/bench/ on first use, so every run
measures the same document and the repository stays small.
Benchmarks run in CI on Linux on every push and report the numbers; a run more than 25 % over a budget fails,
because shared runners are noisy. The budgets themselves are verified on the reference machine before each
milestone, and the results are kept in test/bench/results/<version>.json.