perf: per-app JS budgets (kayg 2026-11-02) #866

Closed
kayg wants to merge 0 commits from perf/budgets-per-app into dev
Owner

replaces the 315 KB aggregate gate with explicit budgets for every emitted JS chunk, using Vite manifest names rather than hashed URLs. first-paint JS stays at 240 KB; CSS stays at 22.1 KB. new chunk names fail the gate until assigned a budget. lazy chunks also fail if moved into the initial HTML load.

budgets use origin/dev and the individual heads of #840, #841, #843, #845, #846, #850, #851, #852 and #853, with small headroom. the existing shared idle-screens group and opt-in vim are the only deferred chunks above 30 KB. index includes shared vendor/editor core; svelte is the shared torph animation library. existing lazy boundaries and warming behavior are preserved.

stable chunk name budget, KB brotli (1024 bytes)
index 240
idle-screens 50.5
Palette 22
ContactsScreen 14.5
TreeSection 3.25
widget 7.25
table-bar.svelte 2.5
PictureViewer 1.1
svelte 9.75
replay 6.25
ListSearch 3.25
InstallHint 1.25
PullHint 1.1
notes-fill.worker 1
two-finger 1
rolldown-runtime 0.5
vim 39

sanity cap: 404.2 KB, exactly the sum above, including opt-in Vim. the existing 45 KB plugin aggregate guard also remains. a build may omit a chunk when that feature is absent. duplicate manifest names share one allowance.

worker URLs retain content hashes for caching; a worker manifest supplies the stable chunk name. gate output prints each emitted chunk with three decimal places so small first-paint regressions remain visible.

validation: dev-01 only, Nix tools and ~/bin/slot. focused Node tests cover unknown chunks, duplicate names, workers, plugin accounting, lazy-to-initial movement and cap consistency. perf/web.sh --bundle-only --gate passes on this implementation branch. independent dev/port matrix results and exact commands will be posted below. no ports are merged and no branches or settings belonging to others are changed.

replaces the 315 KB aggregate gate with explicit budgets for every emitted JS chunk, using Vite manifest names rather than hashed URLs. first-paint JS stays at 240 KB; CSS stays at 22.1 KB. new chunk names fail the gate until assigned a budget. lazy chunks also fail if moved into the initial HTML load. budgets use origin/dev and the individual heads of #840, #841, #843, #845, #846, #850, #851, #852 and #853, with small headroom. the existing shared `idle-screens` group and opt-in `vim` are the only deferred chunks above 30 KB. `index` includes shared vendor/editor core; `svelte` is the shared torph animation library. existing lazy boundaries and warming behavior are preserved. | stable chunk name | budget, KB brotli (1024 bytes) | |---|---:| | `index` | 240 | | `idle-screens` | 50.5 | | `Palette` | 22 | | `ContactsScreen` | 14.5 | | `TreeSection` | 3.25 | | `widget` | 7.25 | | `table-bar.svelte` | 2.5 | | `PictureViewer` | 1.1 | | `svelte` | 9.75 | | `replay` | 6.25 | | `ListSearch` | 3.25 | | `InstallHint` | 1.25 | | `PullHint` | 1.1 | | `notes-fill.worker` | 1 | | `two-finger` | 1 | | `rolldown-runtime` | 0.5 | | `vim` | 39 | sanity cap: **404.2 KB**, exactly the sum above, including opt-in Vim. the existing 45 KB plugin aggregate guard also remains. a build may omit a chunk when that feature is absent. duplicate manifest names share one allowance. worker URLs retain content hashes for caching; a worker manifest supplies the stable chunk name. gate output prints each emitted chunk with three decimal places so small first-paint regressions remain visible. validation: dev-01 only, Nix tools and `~/bin/slot`. focused Node tests cover unknown chunks, duplicate names, workers, plugin accounting, lazy-to-initial movement and cap consistency. `perf/web.sh --bundle-only --gate` passes on this implementation branch. independent dev/port matrix results and exact commands will be posted below. no ports are merged and no branches or settings belonging to others are changed.
perf: gate named app chunks with explicit brotli budgets
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
Markdown extraction contract / markdown-native-contract (pull_request) Has been cancelled
Markdown extraction contract / markdown-editor-contract (pull_request) Has been cancelled
da1071ed09
Author
Owner

final dev-01 bundle matrix, implementation head ba1f47dc94797d4a8a937298464b5e4828e301c2. all sizes below are KB brotli (1024 bytes), quality 11. no port branches were merged or edited.

passes: origin/dev, #843 contacts-card, #845 tables, #850 style, #851 style-2, #852 covers, #853 pickers.

fails: #840 search, #841 contacts-list, #846 images. their named lazy chunks, CSS and total caps all pass. their existing first-paint JS exceeds the unchanged 240 KB cap; the index chunk guard reports the same regression too. #841 is over by 49 bytes, so this is intentionally not rounded away.

build exact source head first JS / 240 first CSS / 22.1 total JS / 404.2 gate exit
dev 55f35fcde3bc91ca3781055577b93e93819f6cd4 239.517 20.860 349.827 0
840 b68ace95fae5fb05a17697a667f69b020630d136 241.566 20.860 361.634 1
841 ef15767cd3b1481a5d29174f690e45aab65100b0 240.048 20.860 355.631 1
843 99e1e394494e2289a26356edb47ee8d8733c9714 239.766 20.860 366.659 0
845 ba606898f41af950ee5d8fcabbfe1e79eb455a33 239.932 20.979 359.355 0
846 8643313b14473fc03f0496dc1f87597991377912 242.147 20.942 353.339 1
850 136defb50ef7039bfb0be76a4d18d175f56a61d8 239.483 21.486 353.411 0
851 bcca58e3d8af37b1246f81ff0a2f55faa4070426 239.633 21.614 355.811 0
852 2f0b59f18406f03ca55b2fe745e3e11fedd9e84d 239.896 21.614 360.011 0
853 2b3f5001fef8a2c9c1c98c3990e4167d50d4af35 233.152 20.393 344.822 0

per-chunk measurements against the explicit budgets. — means that branch does not emit that chunk. each name below comes from the main or worker Vite manifest, never from stripping a filename hash.

stable chunk budget dev 840 841 843 845 846 850 851 852 853
index 240 239.517 241.194 240.048 239.766 239.932 242.147 239.483 239.633 239.896 233.152
idle-screens 50.5 39.219 39.203 39.170 39.192 39.128 39.155 43.090 45.324 49.247 40.550
Palette 22 12.016 21.104 12.028 12.025 12.073 12.015 11.846 11.860 11.862 12.079
ContactsScreen 14.5 — — 5.323 13.577 — — — — — —
TreeSection 3.25 — — — 3.030 — — — — — —
widget 7.25 — — — — 6.914 — — — — —
table-bar.svelte 2.5 — — — — 2.222 — — — — —
PictureViewer 1.1 — — — — — 0.929 — — — —
svelte 9.75 9.321 9.328 9.323 9.327 9.327 9.325 9.311 9.312 9.319 9.322
replay 6.25 5.956 5.698 5.956 5.956 5.956 5.956 5.956 5.956 5.956 5.956
ListSearch 3.25 3.010 3.005 3.007 3.011 3.021 3.028 3.003 3.017 3.007 3.021
InstallHint 1.25 1.117 1.121 1.114 1.122 1.126 1.121 1.115 1.110 1.120 1.113
PullHint 1.1 — 0.971 — — — — — — — —
notes-fill.worker 1 0.902 0.902 0.902 0.902 0.902 0.902 0.902 0.902 0.902 0.902
two-finger 1 0.827 0.815 0.834 0.842 0.831 0.847 0.811 0.817 0.815 0.827
rolldown-runtime 0.5 — 0.372 — — — — — — — —
vim 39 37.942 37.920 37.925 37.908 37.923 37.913 37.895 37.879 37.885 37.899

exact failures:

840: over budget: web.bundle.chunk.index@0: p95 241.194 > 240
840: over budget: web.bundle.first_js_brotli@0: p95 241.566 > 240
841: over budget: web.bundle.chunk.index@0: p95 240.048 > 240
841: over budget: web.bundle.first_js_brotli@0: p95 240.048 > 240
846: over budget: web.bundle.chunk.index@0: p95 242.147 > 240
846: over budget: web.bundle.first_js_brotli@0: p95 242.147 > 240

commands and isolation:

  • VM: netbird ssh claude@calternal-dev-01-compute02.vpn.kayg.org, with more than 300 GB free before builds. all builds used Nix and ~/bin/slot.
  • independent sources: one detached measurement worktree checked out each exact source SHA above, without merging. applied only this PR's manifest: true, workerManifest import/worker plugin config, and worker-manifest plugin file to emit stable metadata. the app source and code-splitting settings stayed those of each source branch. the shared brief's Nix flake overlay supplied the toolchain.
  • at each source: nix develop -c bash -c 'bun install --frozen-lockfile && ~/bin/slot bash -c "cd apps/web && node scripts/fonts.mjs && bunx vite build --outDir /tmp/budgets-per-app-matrix/<id>/dist --emptyOutDir --logLevel warn"'.
  • at the implementation worktree, for every build: PERF_DIST=/tmp/budgets-per-app-matrix/<id>/dist PERF_OUT=/tmp/budgets-per-app-matrix/<id>/gate perf/web.sh --bundle-only --gate, inside nix develop -c bash -c. all ten were rerun using the final head's gate scripts.
  • final implementation: nix develop -c bash -c 'node --test apps/web/scripts/test/bundle-budget.test.mjs': 6 passed, 0 failed.
  • final implementation: nix develop -c bash -c '~/bin/slot perf/web.sh --bundle-only --gate': exit 0, fresh production build, first JS 239.517 KB, total 349.827 KB.
  • git diff --check: clean. builds emit existing Svelte/Vite warnings; these do not fail the bundle gate. this task did not run browser/frame benchmarks or claim runtime timing improvements.

remaining limits: this matrix tests each port independently, not their combined future build. the first-screen budget has very little spare room, and the three failing ports need to reduce initial JS. existing shared idle-screen warming remains unchanged; new named chunks require explicit allowances and deferred chunks cannot move into the initial static import graph. no merge performed.

final dev-01 bundle matrix, implementation head `ba1f47dc94797d4a8a937298464b5e4828e301c2`. all sizes below are KB brotli (1024 bytes), quality 11. no port branches were merged or edited. **passes:** origin/dev, #843 contacts-card, #845 tables, #850 style, #851 style-2, #852 covers, #853 pickers. **fails:** #840 search, #841 contacts-list, #846 images. their named lazy chunks, CSS and total caps all pass. their existing first-paint JS exceeds the unchanged 240 KB cap; the `index` chunk guard reports the same regression too. #841 is over by 49 bytes, so this is intentionally not rounded away. | build | exact source head | first JS / 240 | first CSS / 22.1 | total JS / 404.2 | gate exit | |---|---|---:|---:|---:|---:| | dev | `55f35fcde3bc91ca3781055577b93e93819f6cd4` | 239.517 | 20.860 | 349.827 | 0 | | 840 | `b68ace95fae5fb05a17697a667f69b020630d136` | 241.566 | 20.860 | 361.634 | 1 | | 841 | `ef15767cd3b1481a5d29174f690e45aab65100b0` | 240.048 | 20.860 | 355.631 | 1 | | 843 | `99e1e394494e2289a26356edb47ee8d8733c9714` | 239.766 | 20.860 | 366.659 | 0 | | 845 | `ba606898f41af950ee5d8fcabbfe1e79eb455a33` | 239.932 | 20.979 | 359.355 | 0 | | 846 | `8643313b14473fc03f0496dc1f87597991377912` | 242.147 | 20.942 | 353.339 | 1 | | 850 | `136defb50ef7039bfb0be76a4d18d175f56a61d8` | 239.483 | 21.486 | 353.411 | 0 | | 851 | `bcca58e3d8af37b1246f81ff0a2f55faa4070426` | 239.633 | 21.614 | 355.811 | 0 | | 852 | `2f0b59f18406f03ca55b2fe745e3e11fedd9e84d` | 239.896 | 21.614 | 360.011 | 0 | | 853 | `2b3f5001fef8a2c9c1c98c3990e4167d50d4af35` | 233.152 | 20.393 | 344.822 | 0 | per-chunk measurements against the explicit budgets. `—` means that branch does not emit that chunk. each name below comes from the main or worker Vite manifest, never from stripping a filename hash. | stable chunk | budget | dev | 840 | 841 | 843 | 845 | 846 | 850 | 851 | 852 | 853 | |---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| | `index` | 240 | 239.517 | 241.194 | 240.048 | 239.766 | 239.932 | 242.147 | 239.483 | 239.633 | 239.896 | 233.152 | | `idle-screens` | 50.5 | 39.219 | 39.203 | 39.170 | 39.192 | 39.128 | 39.155 | 43.090 | 45.324 | 49.247 | 40.550 | | `Palette` | 22 | 12.016 | 21.104 | 12.028 | 12.025 | 12.073 | 12.015 | 11.846 | 11.860 | 11.862 | 12.079 | | `ContactsScreen` | 14.5 | — | — | 5.323 | 13.577 | — | — | — | — | — | — | | `TreeSection` | 3.25 | — | — | — | 3.030 | — | — | — | — | — | — | | `widget` | 7.25 | — | — | — | — | 6.914 | — | — | — | — | — | | `table-bar.svelte` | 2.5 | — | — | — | — | 2.222 | — | — | — | — | — | | `PictureViewer` | 1.1 | — | — | — | — | — | 0.929 | — | — | — | — | | `svelte` | 9.75 | 9.321 | 9.328 | 9.323 | 9.327 | 9.327 | 9.325 | 9.311 | 9.312 | 9.319 | 9.322 | | `replay` | 6.25 | 5.956 | 5.698 | 5.956 | 5.956 | 5.956 | 5.956 | 5.956 | 5.956 | 5.956 | 5.956 | | `ListSearch` | 3.25 | 3.010 | 3.005 | 3.007 | 3.011 | 3.021 | 3.028 | 3.003 | 3.017 | 3.007 | 3.021 | | `InstallHint` | 1.25 | 1.117 | 1.121 | 1.114 | 1.122 | 1.126 | 1.121 | 1.115 | 1.110 | 1.120 | 1.113 | | `PullHint` | 1.1 | — | 0.971 | — | — | — | — | — | — | — | — | | `notes-fill.worker` | 1 | 0.902 | 0.902 | 0.902 | 0.902 | 0.902 | 0.902 | 0.902 | 0.902 | 0.902 | 0.902 | | `two-finger` | 1 | 0.827 | 0.815 | 0.834 | 0.842 | 0.831 | 0.847 | 0.811 | 0.817 | 0.815 | 0.827 | | `rolldown-runtime` | 0.5 | — | 0.372 | — | — | — | — | — | — | — | — | | `vim` | 39 | 37.942 | 37.920 | 37.925 | 37.908 | 37.923 | 37.913 | 37.895 | 37.879 | 37.885 | 37.899 | exact failures: ``` 840: over budget: web.bundle.chunk.index@0: p95 241.194 > 240 840: over budget: web.bundle.first_js_brotli@0: p95 241.566 > 240 841: over budget: web.bundle.chunk.index@0: p95 240.048 > 240 841: over budget: web.bundle.first_js_brotli@0: p95 240.048 > 240 846: over budget: web.bundle.chunk.index@0: p95 242.147 > 240 846: over budget: web.bundle.first_js_brotli@0: p95 242.147 > 240 ``` commands and isolation: - VM: `netbird ssh claude@calternal-dev-01-compute02.vpn.kayg.org`, with more than 300 GB free before builds. all builds used Nix and `~/bin/slot`. - independent sources: one detached measurement worktree checked out each exact source SHA above, without merging. applied only this PR's `manifest: true`, `workerManifest` import/worker plugin config, and worker-manifest plugin file to emit stable metadata. the app source and code-splitting settings stayed those of each source branch. the shared brief's Nix flake overlay supplied the toolchain. - at each source: `nix develop -c bash -c 'bun install --frozen-lockfile && ~/bin/slot bash -c "cd apps/web && node scripts/fonts.mjs && bunx vite build --outDir /tmp/budgets-per-app-matrix/<id>/dist --emptyOutDir --logLevel warn"'`. - at the implementation worktree, for **every** build: `PERF_DIST=/tmp/budgets-per-app-matrix/<id>/dist PERF_OUT=/tmp/budgets-per-app-matrix/<id>/gate perf/web.sh --bundle-only --gate`, inside `nix develop -c bash -c`. all ten were rerun using the final head's gate scripts. - final implementation: `nix develop -c bash -c 'node --test apps/web/scripts/test/bundle-budget.test.mjs'`: **6 passed, 0 failed**. - final implementation: `nix develop -c bash -c '~/bin/slot perf/web.sh --bundle-only --gate'`: **exit 0**, fresh production build, first JS **239.517 KB**, total **349.827 KB**. - `git diff --check`: clean. builds emit existing Svelte/Vite warnings; these do not fail the bundle gate. this task did not run browser/frame benchmarks or claim runtime timing improvements. remaining limits: this matrix tests each port independently, not their combined future build. the first-screen budget has very little spare room, and the three failing ports need to reduce initial JS. existing shared idle-screen warming remains unchanged; new named chunks require explicit allowances and deferred chunks cannot move into the initial static import graph. no merge performed.
Author
Owner

Closing: head ba1f47dc is already in dev (reached via fa7e568f); nothing left to merge. Branch kept.

Closing: head ba1f47dc is already in dev (reached via fa7e568f); nothing left to merge. Branch kept.
kayg closed this pull request 2026-11-04 13:05:01 +00:00
Some checks failed
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
Markdown extraction contract / markdown-native-contract (pull_request) Has been cancelled
Markdown extraction contract / markdown-editor-contract (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!866
No description provided.