CE optimization roadmap
Performance work, prioritized. Grounded in the measured benchmark findings in ce-bench/docs/network-benchmark-findings.md and ce-bench/docs/app-benchmark-findings.md.
Done (2026-06-25)
- F4 —
put_blobfire-and-forget DHT announce (was the ~1s write floor; 1 MiB PUT now ~10 ms). - F2 — blob read/write in
spawn_blocking(off the async runtime; kills the p99 tails). - Placement (data) —
fetch_chunk_from_meshranks providers by/netgraphRTT and races the nearest few in parallel (first CID-valid wins) instead of a random sequential scan. - F7 — self-request short-circuit (node PR #3).
- App-layer (in the app repos): D1 push-stream serve loop, D3 parallel object chunks, D5 cached open snapshot.
Remaining — NOT yet implemented
P1 — transport core (the latency/throughput ceiling)
- F1 — single-
SwarmRPC serialization. Every RPC funnels through the one libp2pSwarmevent loop (Meshis!Sync), so wire I/O serializes — that's the ~25-50 req/s ceiling and the per-op ~17 ms floor even at zero network distance. Directions: a dedicated RPC connection pool / multiple connections per peer; reduce the hop chain (HTTP handler →cmd_txmpsc → swarm →event_txmpsc → node loop → oneshot) to fewer awaits; consider splitting bulk vs control planes. - QUIC-first RPC. Prefer QUIC for the
/ce/rpc/1substreams to avoid TCP head-of-line blocking, and verify/raise the concurrent-substream limits so parallel requests actually parallelize. - F3 — bulk transfer off AppRequest. Large directed-RPC payloads run ~0.5-1 MB/s. Route bulk bytes over dedicated libp2p streams (the
FetchChunk/data path), chunked + parallel, rather than the request/reply AppRequest channel.
P1 — data path
- Node
/blobsbody limit + streaming. The/blobsroute has a small default axum body limit (~2 MB); raw single-blob PUTs above it are rejected (the apparent "8 MiB RST"). RaiseDefaultBodyLimiton the blob routes and stream the PUT body to disk instead of buffering it whole. (Apps chunk to 1 MiB so they're unaffected today; this is for raw large-blob users.) - Blob GET ranges/streaming. Serve
Rangerequests and stream large blobs from disk without materializing the whole body in memory. - Durability on write. Pin written/fetched chunks at a replication factor (ce-pin) so bytes survive the uploader, instead of relying on a single provider record.
P2 — placement & resilience
- Compute placement. Atlas +
/netgraphRTT-guided host selection indeploy/ce-sched: prefer low-latency, same-region, capacity-fit hosts; vendor-aware. (Data placement is done; this is the job-placement side.) - F6 — relay/bootstrap keepalive + auto-redial. Long-lived nodes silently lose the relay link (observed: laptop↔relay last-seen 7.4 h, directed traffic then "fails to dial"). Add keepalive + automatic redial of bootstrap/relay peers.
P2 — app layer (tracked in the app repos, listed here for completeness)
- ce-drive Mirror incremental-apply (M3).
Mirror::syncre-bootstraps the whole tree on any change; apply feed deltas incrementally instead of a full snapshot refetch. - Snapshot debounce. If snapshot republish ever moves onto the write path, debounce it rather than per-op.
How to validate
Use the ce-bench harnesses: ce-netbench (primitives over the real mesh), bench-s3.js (ce-storage), ce-drive-client/examples/bench_drive (ce-drive two-node mesh). Always validate blob perf on a real-DHT node — the ephemeral 2-node bench understates data-path wins (the provide churns the single Swarm with no real DHT).