perf: stop spurious mesh epoch churn; drop per-chunk zero-fill in silkd bulk path - #53
Merged
Conversation
Map-iteration order made UpdateSelf's order-sensitive compare misfire on most 1s ticks once two or more promoted templates existed: each misfire cost a spurious epoch bump, a double-fsync persist, and a cluster-wide re-merge of this node's state.
The scratch buffer is now grow-only: resize's zero-fill ran on every output chunk (~349KB memset per 256KB chunk, immediately overwritten by encode_slice) and is now paid once at high-water. bench_chunk_render 32768 x 256KB chunks: 4.08s -> 2.31s (~1.77x) on the hand-rendered path.
dialAgent writes the fixed-shape upgrade request directly (16 -> 2 allocs/op) with the same control-character guard as the Python SDK; frame scanning moves to wire.NewFrameScanner shared with sandboxd's engine, dropping the 64KB pre-sized buffer both copies paid per conn; ReadFile retains decoded chunks instead of re-copying through append growth, with the retention contract documented on DecodeResponse. The silkdtest fake now chunks downloads at silkd's real frame size.
Raw data-plane sockets left Nagle on (Go's net.Dial disables it); small back-to-back frames risked delayed-ACK stalls off-loopback. FS_CHUNK now matches silkd's 256K frame chunk instead of 32K — 8x fewer frames on large writes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes out of a static performance pass over sandboxd, the Rust crates, the SDKs, protocol/wire, and mcp.
sandboxd: sort template hashes so the mesh unchanged-guard holds
TemplateHashesreturned map-iteration order whileUpdateSelfcompares thetemplate list order-sensitively (
slices.Equal). With two or more promotedtemplates the "unchanged view" guard misfired on a large fraction of 1s gossip
ticks — each misfire a spurious epoch bump: a durable double-fsync persist plus
a cluster-wide republish and re-merge. One-line fix, regression test pinning
the canonical order, and
UpdateSelfnow documents the sorted contract.Measured (mesh of one, 3 promoted templates, 60s): epoch delta +19 → 0.
silkd: drop the per-chunk zero-fill in write_chunk_frame
The scratch buffer was cleared and
resize(.., 0)-extended per chunk,memsetting the whole base64 region (~349KB per 256KB bulk chunk) that
encode_sliceimmediately overwrites — on every stdout/stderr/data frame ofevery streaming verb. The buffer is now grow-only: the zero-fill runs once at
high-water and each frame fully overwrites
buf[..total].Micro-bench (
bench_chunk_render_old_vs_new, release): 32768 x 256KB chunks4.08s → 2.31s (~1.77x). Bare-metal A/B (Ryzen 9700X, same sandboxd, old vs new
silkd in the same rt:24.04 base, two rounds each): fs_pull 963.2/969.0 vs
948.6/842.5 MiB/s — new ≥ old in every pairing and materially tighter; exec
RTT, claim tiers, cold boot, refill recovery unchanged.
sdk/go + protocol/wire: trim the per-RPC dial and read path
dialAgentwrites the fixed-shape upgrade request directly instead ofdriving
http.Request.Write(measured 16 → 2 allocs/op), with the samecontrol-character guard the Python SDK already had (plus a regression test).
wire.NewFrameScanner, shared by the SDKand sandboxd's engine — both copies previously pre-allocated a zeroed 64KB
buffer per connection that bulk frames outgrew anyway.
ReadFileretains decoded chunks and concatenates once instead of payingappend-growth re-copies; the retention contract is documented on
DecodeResponse, and the silkdtest fake now chunks downloads at silkd'sreal 256KB frame size (multi-chunk path is now tested).
Bare-metal A/B (same daemon and template, old vs new SDK bench binaries, two
rounds each): exec RTT p50 0.21/0.17ms vs 0.22/0.21ms, fs_pull 792.6/975.8 vs
768.6/907.0 MiB/s — new ≤/≥ old respectively in every pairing, no regression.
sdk/python: TCP_NODELAY + 256K fs chunks
Raw data-plane sockets left Nagle enabled (Go's
net.Dialdisables it bydefault); small back-to-back frames risked delayed-ACK stalls once client and
node are not co-located.
FS_CHUNKrises 32K → 256K to match silkd's framechunk — 8x fewer frames on large writes.
Measured (8MiB
write_file, bare metal, median of 6): 27.9ms → 25.5ms (~9%).Gates
go test -raceacross sandboxd, sdk/go, protocol/wire, e2e; golangci-lintlinux+darwin 0 issues; asl clean both GOOS;
cargo fmt --check+clippy -D warnings+cargo testclean;ruff checkclean; 136 Python tests pass.