Tune bounded receive windows against the paced product workload #80
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem and evidence
The production browser stream defaults to a 256 KiB receive window and coalesces CREDIT for up to 6 ms (packages/stream/src/index.ts:3-13, 801-822); protocol caps are 4 MiB per channel and 8 MiB per connection. With 306 Docker and 306 Podman fixtures, remote Docker 32 MiB exec output measured 16.381 / 29.793 / 33.460 MiB/s at 256 KiB / 1 MiB / 4 MiB windows (load1 roughly 25–34). A lower-load byte-exact PTY cross-check measured remote Docker 18.141→43.451 MiB/s and Podman 23.595→67.354 MiB/s at 256 KiB→1 MiB (load1 11.10–11.82).
See named-stream-output.svg, pty-summary.json and pty-batched.json.
Recommendation
Test a bounded adaptive 512 KiB–1 MiB receive window and return credit before depletion, while respecting control-frame limits and aggregate direction caps. Measure per-stream RSS and concurrent streams; do not allocate 4 MiB for every channel by default.
Payoff, effort and risk
Expected gain: the measured remote Docker exec path improved 1.82× at 1 MiB and 2.04× at 4 MiB; the lower-load exact PTY cross-check improved 2.40× for Docker and 2.85× for Podman at 1 MiB.
Quick win vs deeper change: bounded window experiment ≤½ day; accepted policy plus per-stream and aggregate memory checks is deeper, estimated 1–2 days.
Risk: medium; larger reservations may raise RSS or starve control frames under concurrency.
Priority: Now (≤1 day for the experiment).
2026-10-04 owner decisions: Matches performance-first and the custom v1 WebSocket protocol. Retain the 8 MiB aggregate and 4 MiB channel limits; no new stream path. Related: #60.
Report: perf-audit report
Source: perf-audit 2026-10-04
Started perf-logs-windows, sole writer in /mnt/hdd/infraternal/wt-lp/perf-logs-windows. Branch perf-logs-windows; base/head
173525d835. Scope: log decoder allocations and measured bounded receive-window policy; preserve #77 batched credit and revocation deadlines. Will run targeted stream/decoder tests, throughput and 32 MiB remote-upload regression, then INFRATERNAL_VERIFY_RUN_ID=perf-logs-windows scripts/verify fast; no merge gate or push. Reading audit scripts and searching for missing perf-test-vm workflow; dev-VM diagnostics will be explicitly distinguished from perf-test-VM certification.Window experiment uses the existing simultaneous browser workload: 500+ echo round trips while a nonbursting FIFO emits four 16,001-byte lines per 1,100 us (~55.489 MiB/s nominal). Three alternating trials per 256 KiB / 512 KiB / 1 MiB setting, embedded/remote Docker and rootless Podman; real release server, enrolled mTLS infraternal agent, actual source byte/time counters and loaded RSS. The shared benchmark now defaults to product windows rather than hardcoding 4 MiB; optional override is only for measured experiments. CREDIT remains globally coalesced at 6 ms; no server/native credit, signing, audit or authorization-path change.
Source inspection: StreamService uses 64 global / 4 per-user client upgrades; each direction keeps the 8 MiB connection budget. The 500-host / 20,000-container inventory goal must not be modeled as one always-open log subscription per container. Final memory math and selected setting follow the measurements.
Perf-test-VM certification is unavailable in this job: .claude/skills/perf-test-vm/SKILL.md is missing, and the skill was not found in the local Codex/Claude skill locations. No remote perf-test VM workflow or connection contract is available. Continuing the authorized implementation, real-service regressions and explicitly labeled Debian dev-VM diagnostics; no absolute performance certification or threshold relaxation is claimed. The integration lead must run the perf-test-VM A/B and independent review before merging.
Initial paced-window run returned 12 valid trials, then stopped on OPEN_ERR not_found for a newly created fixture before inventory publication. Cleanup completed. Added an observed inventory-publication fence using the existing harness and load1 <=10 admission before each timing trial; incomplete matrix retained separately and will not supply final medians.
The initial embedded Docker trials show why throughput alone is insufficient: medians 17.821 / 27.983 / 40.935 MiB/s at 256 KiB / 512 KiB / 1 MiB, with echo p99 23.3 / 33.2 / 41.3 ms. Source emitted ~50–54 MiB/s; peak server RSS <=36.719 MiB. Several initial trials reached load1 >10 and are diagnostic only. A blanket larger log default is not justified by these results; final policy must avoid adopting a known echo regression.
perf-logs-windows — #83 / #80
Head:
79b211653663437edae7968aaa82a4507d14648a. Branch:perf-logs-windows. Base:173525d8358a2576e681576605a7a7c5f1b9ebdd. Three logical commits; no push, merge gate, issue closure, other AI agents or systemd units.Changes
The log decoder reuses its 13-byte header DataView. Two uint32 words replace per-record BigInts; only nonzero exact 53-bit timestamps become numbers, with unsafe uint64 values still null. Split headers/bodies and UTF-8 behavior remain bounded and covered by tests.
TypeScript declares 1 MiB output receive windows for exec/SSH and keeps logs/events/stats at 256 KiB. OPEN always carries the same size reserved locally; Rust omitted-field defaults and native input windows remain 256 KiB. The six-ms connection-wide CREDIT scheduler, #77 native input batching, signing, audit, authorization and Rust stream paths are unchanged. The simultaneous benchmark now uses actual product defaults rather than a hardcoded 4 MiB log window.
Decoder allocation A/B
Chromium sampled decoder allocations: 32,656,644 → 23,933,944 bytes, 26.71% lower, medians of three alternating trials. Each trial: 100,000 records at 10,000 lines/s, 99-byte bodies + 13-byte headers, 100 records/feed, about 10 seconds. All retain exactly 10,000 lines / 990,000 body bytes and zero partial records. Load1 3.56–4.77.
The profiler samples at 1,024 bytes and includes objects collected by both major and minor GC; numbers are estimates, not exact allocation counts. JavaScript objects live inside V8 and cannot be attributed by native dhat/heaptrack. This uses the appropriate Chromium heap profiler instead. No browser rendering/frame-time improvement is claimed.
Reproduce:
bun e2e/remote/log-decoder-bench.ts BASE_SOURCE packages/web/src/lib/log-stream.ts; extract BASE_SOURCE withgit show 173525d:packages/web/src/lib/log-stream.ts. Raw:decoder-ab.jsonl. Method: Chromium HeapProfiler; timestamp semantics: ECMAScript safe integers and uint32 DataView reads.PTY capacity A/B
Three trials per path/window, 32 MiB batched native PTY output, six-ms credit return; exact byte counts and exit status checked in all 36 trials. MiB/s below measures first-to-last DATA, excluding OPEN and the source’s final one-second sleep. Server/native Rust is identical to the base. Load1 3.68–5.14. These are protocol capacity diagnostics, not xterm ingestion certification.
Raw:
pty-batched.json,pty.log,pty-batched.tsadapted from the audit with this worktree’s harness, release binary, owned label and 512 KiB comparison. Batched source code is/mnt/hdd/infraternal/jobs/perf-audit/terminal-source.c.Paced simultaneous workload and policy choice
The source targets 55.490 MiB/s (four 16,001-byte lines per 1,100 us), with no catch-up bursts; every successful trial includes at least 500 browser echo samples. It uses the existing browser workload through the real release server and enrolled mTLS infraternal agent, with the current TypeScript client bundled for the browser. Actual source throughput was also measured. Real rootful Docker and rootless Podman; fixture log-file cap 1 MiB matches the existing paced benchmark.
The controlled window experiment completed nine embedded Docker and three remote Docker trials before a between-trial
host_offlinerefusal. An earlier run stopped on a newly created fixture’snot_found; its higher-load results are excluded from the controlled table. Neither partial run is presented as a complete provider matrix. Inventory-publication/load admission fences were added to the diagnostic; final policy timing trials additionally assert no tunnel-generation replacement.Controlled window load1 2.17–7.66. Larger log windows improve throughput but systematically worsen echo. They are not adopted. Standalone PTY gains justify the 1 MiB terminal window; larger terminal credit does not add source batching or relax admission.
The complete chosen-policy A/B has three alternating trials per setting/path: old explicit 256 KiB for both channels versus product defaults (256 KiB logs / 1 MiB terminals). All 24 timing trials preserve the tunnel generation. Actual source emitted 38.961–55.165 MiB/s; load1 1.84–9.96.
Peak sampled server RSS (10-ms sampling) was 38.273 MiB. After warming, eight real simultaneous 1 MiB log overrides showed server RSS 38.273 → 38.273 MiB; the ninth OPEN was refused, all CLOSE acknowledgments arrived and a replacement OPEN succeeded. This is a warm RSS observation, not zero allocated bytes or an exact unsampled peak.
Performance certification remains blocked: logs are below 50 MiB/s, multiple echo paths exceed both the 5-ms absolute and 10-ms dev criteria, and final remote echo medians are higher than baseline. Shared-load dev results do not establish an acceptable echo regression or justify relaxing thresholds. The rootless source did not sustain the nominal target in every trial. This job does not certify the simultaneous budget or recommend merging on the fast gate alone. Run the exact candidate/base A/B on the perf-test VM before merge; the required
perf-test-vmskill/connection workflow is unavailable locally. Rendering-frame and xterm-ingest budgets were not measured.Raw controlled experiment:
windows-controlled-partial.json; final matrix:final-policy/windows.json; runnable diagnostic:e2e/remote/window-bench.ts.STREAM_WINDOWS=262144,0reproduces the old/default comparison (0 selects per-kind defaults). The default script setting compares 256 KiB / 512 KiB / 1 MiB explicitly. SetINFRATERNAL_E2E_BINARYto the built release binary andINFRATERNAL_ARTIFACT_DIRto a private artifact directory.Memory math at 500 hosts / 20,000 containers
Correctness and verification
forbiddenCLOSE received in 3.426 / 93.112 / 86.855 / 46.989 ms, all within C+850 ms. Owned physical tunnel stop: auditedhost_offlinein 2.699 ms. Raw:upload-regression.log; driver is the existing binary-stream regression adapted only for label/output directory, 32 MiB selection and 1 MiB output declaration.infraternal.test=perf-logs-windows; final Docker/Podman label queries return no IDs. No other fixtures removed.The first fast-gate attempt failed the package-import declaration check because the allocation script was placed under packages/web. Moving it to the root-owned e2e directory uses the existing Playwright declaration without adding a dependency. Final fast result follows.
Final gate
PASS (exit 0):
INFRATERNAL_VERIFY_RUN_ID=perf-logs-windows scripts/verify fast. Never ran verify merge.Verbatim gate output: