Public: anyone can read this; the crew can change it.
The code-page worker pool is sized from the machine, and the cold 500/s bench says what it bought #9674
Check · Review · Land · Live done — Landed and live in production.
The code-page worker pool's size can now be set with `FORGE_CODE_ROWS_WORKERS`, but the default stays at 2 workers. Sizing the pool from the machine did not cut refusals beyond noise in the cold 500/s bench, which is the case where the issue says the default stays 2.
shipped production is serving it deploy f21b126
The code-page worker pool's size can now be set with FORGE_CODE_ROWS_WORKERS, but the default stays at 2 workers. Sizing the pool from the machine did not cut refusals beyond noise in the cold 500/s bench, which is the case where the issue says the default stays 2.
What changed
src/web/code_rows_pool.ts:poolSize()readsFORGE_CODE_ROWS_WORKERS, like the git pool'sFORGE_GIT_CONCURRENCY:
- a number is floored and capped at 8;
- auto uses the machine's available parallelism, kept between 2 and 8 (exported as machineWorkers());
- unset, or any bad value, gives 2.
- The cap of 8: its reason is written beside it. Each worker is about 8 MB of heap when idle (measured here), and a cold page also needs cores for git.
- Tests:
test/code-rows-pool-size.test.tscovers the default, numeric overrides,auto, the bad values ("",0,-2,0.5,two,NaN,Infinity,AUTO) falling back to 2, and the environment variable actually being read. - Docs: one line in
docs/features/load-test.md. - Bench:
bench/results/cold-forge-500.mdgains an "After the pool" section.
What the bench showed
Six runs of bun bench/code-pages-at-rate.ts --rate 500 --seconds 20 --warm 0 --crawl 3000, alternating sizes, on this 80-core machine (so auto is 8):
| refused | p95 | |
|---|---|---|
| 8 workers | 1,919 / 1,918 / 2,099 | 382–414 ms |
| 2 workers | 2,661 / 2,945 / 2,143 | 451–595 ms |
The 8-worker results fall inside the 2-worker range: main's earlier 2-worker runs refused as few as 1,802. In the last back-to-back pair the gap was 44. Throughput still levels off near 400 a second with either size, so the pool is not the limit. That fits the earlier finding that the strangers' in-flight test does the refusing.
Chosen not to do
- I did not make the machine-sized pool the default, since the measurement didn't support it.
- I did not try the other lever named in the bench file: counting queueing at the worker pool instead of at the strangers' gate.
To try it: run the bench with FORGE_CODE_ROWS_WORKERS=auto, then =2, and compare. Run the tests with bun test test/code-rows-pool-size.test.ts test/code-rows-worker.test.ts.
Checks run: gate, tsc --noEmit and design-lint are clean. scripts/fast.ts named 1,216 test files because the pool is imported widely, so I ran the covering tests by hand instead (pool size, worker, blob window and long-file, kept-page headers, stranger-code, cold-read): 43 pass from the repository root. The full suite was left to the forge's check.
🤖 Generated with Claude Code
The code-page worker pool no longer starts a fixed two workers. It now reads FORGE_CODE_ROWS_WORKERS once at startup, the same way the git pool reads FORGE_GIT_CONCURRENCY:
- A positive number is rounded down and capped at 8.
autouses the machine's core count, kept between 2 and 8.- Unset or anything else keeps the old default of 2.
The default stays at 2 because the bench didn't justify more. With 8 workers on the 80-core box, a cold crawl at 500 requests a second refused about as many requests as with 2, and throughput still levelled off near 400 served a second. bench/results/cold-forge-500.md has the before and after numbers, and docs/features/load-test.md documents the setting. The cap of 8 is there because each worker is its own JavaScript heap, about 8 MB idle (measured), and cold pages also need cores for git.
What to look at: poolSize and machineWorkers in src/web/code_rows_pool.ts. test/code-rows-pool-size.test.ts covers the unset default, auto at 1, 6 and 80 cores, rounding and capping of numbers, rejected values, and reading the real environment variable.
Not done: the pool can't be resized while the forge is running, and the default doesn't follow the machine's size. The bench showed no gain from more workers.
Earlier failure: the first push was red because the gate requires a Try: line in a commit message, and none had one. A second, empty commit adds it. The preview itself was healthy: /, /healthz and /readyz answered 200, and the SIGTERM at the end of the deploy log was the forge stopping it, not a crash.
Checks: bun scripts/gate.ts, bun x tsc --noEmit, bun scripts/design-lint.ts and bun test test/code-rows-pool-size.test.ts (5 pass) are all green here.
Try: open /preview-admin/sample/blob/main/README.md on the preview. The highlighted rows render through the default pool of two.
🤖 Generated with Claude Code
Approved. The pool is sized by FORGE_CODE_ROWS_WORKERS (a number capped at 8, or auto within [2,8]). Bad values fall back to 2. The tests would fail without the change. The bench section reports six runs and says plainly that the default stays 2. No page changed, so the design principles are not engaged, and there is no new door to mirror in the terminal. Two things to do next: (1) fix the stale line in the bench file saying no code under src/ changes; (2) make the memory figure agree: the bench says about 64 MB idle, the code comment says near 100 MB.
The code-page worker pool's size can now be set with
FORGE_CODE_ROWS_WORKERS, but the default stays at 2 workers. Sizing the pool from the machine did not cut refusals beyond noise in the cold 500/s bench, which is the case where the issue says the default stays 2.What changed
src/web/code_rows_pool.ts:poolSize()readsFORGE_CODE_ROWS_WORKERS, like the git pool'sFORGE_GIT_CONCURRENCY:- a number is floored and capped at 8; -
autouses the machine's available parallelism, kept between 2 and 8 (exported asmachineWorkers()); - unset, or any bad value, gives 2.test/code-rows-pool-size.test.tscovers the default, numeric overrides,auto, the bad values ("",0,-2,0.5,two,NaN,Infinity,AUTO) falling back to 2, and the environment variable actually being read.docs/features/load-test.md.bench/results/cold-forge-500.mdgains an "After the pool" section.What the bench showed
Six runs of
bun bench/code-pages-at-rate.ts --rate 500 --seconds 20 --warm 0 --crawl 3000, alternating sizes, on this 80-core machine (soautois 8):The 8-worker results fall inside the 2-worker range: main's earlier 2-worker runs refused as few as 1,802. In the last back-to-back pair the gap was 44. Throughput still levels off near 400 a second with either size, so the pool is not the limit. That fits the earlier finding that the strangers' in-flight test does the refusing.
Chosen not to do
To try it: run the bench with
FORGE_CODE_ROWS_WORKERS=auto, then=2, and compare. Run the tests withbun test test/code-rows-pool-size.test.ts test/code-rows-worker.test.ts.Checks run: gate,
tsc --noEmitand design-lint are clean.scripts/fast.tsnamed 1,216 test files because the pool is imported widely, so I ran the covering tests by hand instead (pool size, worker, blob window and long-file, kept-page headers, stranger-code, cold-read): 43 pass from the repository root. The full suite was left to the forge's check.🤖 Generated with Claude Code
Closes #9671