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.