Repository navigation
Description
Summary
The Linux series ran on 2026-11-14, with one REST replica at --cpus=1 --memory=512m. It answered the production question for most shapes (REPORT.md §1). This issue tracks what is still owed: shapes not run, single sessions, and sessions the OOM kill voided.
Measured
| Scenario | Session | Verdict | Result |
|---|---|---|---|
| miss-fast (open loop) | 20261114T040347 |
void: OOM kill at miss-fast@6400 |
1600/s rule-valid; CPU, then memory, then kill at 6400/s |
| miss-fast closed loop | 20261114T050553 |
valid | 5186.73/s at c16; plateau knee at c32; best 5665.53/s at c64; no break |
| hit | 20261114T041002 |
valid | no knee to 12800/s (a floor) |
| image | 20261114T041519, 20261114T041855 |
void: OOM kill | memory.max at 100/s; kill at 100/s (run 1) and in the 200/s warm-up (run 2) |
| hostile | 20261114T042447 |
void: OOM kill at hostile@96 |
48/s held |
| hang | 20261114T050053 |
valid | held at hang@20; knee at hang@40 |
| icon | 20261114T043114 |
valid, 1 void step | 100/s rule-valid; valid steps to 3200/s |
| aa | 20261114T043619 |
valid | p50 shift 0.18 ms significant; p99 MDE80 2.08 ms |
- Void and lost reruns: hang
20261114T043005and closed loop20261114T043953(aborted: SIGTERM, the run agent ended its turn). Hang20261114T045241and closed loop20261114T045740(XProtect andlogdCPU at an edge). - Known limits: the VM does not charge socket and slab memory (
nokmem,nosocket). The healthcheck was off. VM timer wake-ups add about 4 ms to the p99 at 200/s or less.
Cause
Owed work, not a defect.
What to change
- Run the shapes that did not run on Linux:
miss-real,huge,herd,redis-stallandlimiter.miss-realcomes first, because it is the production shape. - Repeat every scenario to k ≥ 2.
- Run
hangwith steps at 24, 28, 32 and 36, to place the knee between hang@20 and hang@40. - Run
hitabove 12800/s. - Run an
iconsession on a quiet host, so the knee scan reaches 3200/s. - Get valid
image,hostileand open-loopmiss-fastsessions. Either run them after Link metadata: stream image relays or cap image bytes in flight #786 and Link metadata: shed cold work before the queue grows to an OOM kill #787, or stop each ramp before the kill step. - Repeat
aa, because its p50 shift was significant. - Run the Docker-backend smokes owed on macOS: step0, aa and redis-stall.
- Add a parse-attributed block timer for hostile pages (REPORT.md §3).
- Keep the run agent alive until each session footer is written (REPORT.md §5.7 item 7).
- Done:
LINUX-SERIES.mdnow says the series ran.
Decisions
- Change the send-lag limit inside the VM? Recommended: not yet. Count the void hit steps first, then rule.
- Stop a ramp at the first OOM kill? Recommended: yes, for the after runs of Link metadata: stream image relays or cap image bytes in flight #786 and Link metadata: shed cold work before the queue grows to an OOM kill #787. A kill ends the session anyway.
- Which Redis? Recommended: keep
redis:alpine8.8.0, recorded, as its own fact group. - Measure the core speed ratio to a production vCPU? Recommended: yes, with one short CPU-bound probe on the production host. The maintainer approves, because it touches production.
Benchmark
Before
The table in Measured. LINUX-RESULTS.md holds the full step tables. The hang and closed-loop reruns are in raw/linux/logs/{hang,miss-fast-conc}-rerun2.{replay,breaks}.out.
After
For each route, report:
- the rate where
throttled_usecstarts to rise; - the
memory.currentmax per step, andmemory.events; - each
oom_kill, with its rate.
Condition
The Linux condition in Bench conditions below. It must say: a Linux VM on one laptop, not the production host. The core speed ratio to a production vCPU is not measured.
Content-safety checks
- None. The bench runs under
--network noneand touches no production data.
UX checks
- None. No reader-facing change.
Rollback
None needed. The work stays in local notes and the bench harness (1a0d21b7f).
Acceptance criteria
-
miss-realhas a valid Linux session. - Every scenario has k ≥ 2 valid Linux sessions, or a note on why not.
- The hang knee is placed between hang@20 and hang@40.
- The Linux numbers stay in their own fact group, never mixed with macOS numbers.
- The status lines in
LINUX-SERIES.mdmatch the runs.
Related
- REPORT.md §1 (Linux series status) and §5.8.
- Link metadata: stream image relays or cap image bytes in flight #786 to Link metadata: join concurrent misses for one URL #791 need their Linux after from this runner.
Bench conditions
The bench is apps/hocuspocus.server/scripts/bench-link-tolerance/ (commit 1a0d21b7f). The headline numbers are in apps/hocuspocus.server/src/modules/link-metadata/BENCHMARK.md, section Load tolerance. REPORT.md, LINUX-RESULTS.md, research-*.md and raw/ are local bench notes (Notes/local-docs/2026-11-13-link-scraper-tolerance/), not in the repo. The Linux runner is local too.
Linux condition, used by every "Linux before": one REST container at --cpus=1 --memory=512m --memory-swap=512m, in the OrbStack VM on one laptop. Kernel 7.2.12-orbstack-00394-gbecdd6130068, booted with cgroup.memory=nokmem,nosocket, so socket and slab memory are not charged. --no-healthcheck. Bun 1.4.4+38afee6c8. Redis 8.8.0 (redis:alpine) in REST's network namespace. --network none. Pooled loopback to one local origin, no DNS, no TLS. benchTree 8774a6275a05005f, srcTree a9b6ca73ca68c2ec, runnerTree 516099a8c9839eac. Measured 2026-11-14. The core speed ratio to a production vCPU is not measured.
Laptop condition, used by every "Laptop before": local, one laptop (Apple M5 Max, 18 cores, 48 GB, macOS), Bun 1.4.4+38afee6c8, native Redis 8.10.3. REST runs under the sandbox-exec fence. Traffic is plain HTTP to one local origin, pooled loopback, no DNS, no TLS. No CPU quota and no cgroup. benchTree 8774a6275a05005f, srcTree a9b6ca73ca68c2ec. Measured 2026-11-14. Never compare it with a Linux number as one series.
"(void session)" marks a value from a valid step inside a void session. On Linux the OOM kill voided those sessions. The kill is the measured break.
After method, used by every "After":
- Base = the commit before the change. Head = the change.
- Run ABAB, at least 3 sessions per arm, each with its control step, at n ≥ 2,000 per step.
- The change moves
srcTree, so the before must run again. Do not reuse the 2026-11-14 numbers as the before. - The runner takes
src/from the working tree. So it first needs a source-folder option for base (REPORT.md §5.7 item 5). - On Linux, start each session in a fresh REST container, and keep the run agent alive until the footer is written.
- Quote a change only when every head session sits outside the base range. Give σ and the MDE beside it.
Paths are under apps/hocuspocus.server/src/ unless they say otherwise.
Activity