diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-16 11:11:25 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-16 11:11:25 +0200 |
| commit | 1557ba53d8a7110869484ac5f9ccf03c5cfea322 (patch) | |
| tree | b3178a6efe0effda68160b5ee2aaa83165877650 /CLAUDE.md | |
| parent | 625b2fea074e1c23b992b5759126595b6850af32 (diff) | |
| parent | 595d316f18576356182d81923b28b861bbaec2cc (diff) | |
| download | meshbay-1557ba53d8a7110869484ac5f9ccf03c5cfea322.tar.gz | |
Merge branch 'main' of meshbay.org:meshbay
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 41 |
1 files changed, 41 insertions, 0 deletions
@@ -761,6 +761,47 @@ do. Read them before writing anything that touches the same mechanism. socket buffer gave 19.5 MB/s (`udp_buffer.py`); it needs `net.core.rmem_max` raised on a default machine +- **A transfer capped with a core busy: profile that process before tuning + the network.** The command-line client downloaded at 19 MB/s on loopback. + Its 4 MB receive buffer removed 3245 kernel drops and changed nothing else; + `top` then showed the client, not the node, at 100 %, and cProfile (a + wrapper script as `MESHBAY_CLI_E2E_BIN`, the e2e harness does the rest) put + two thirds of its time in aiortc's `InboundStream.pop_messages`: 153 million + steps for 400 MB, the reassembly walked from its start after every fragment. + Next, a SACK per packet cost the node more than sending. Both fixed in + `sctp_fix.py`: 39 MB/s, the node at 49. No amount of reading our code finds + a quadratic loop in a dependency; one profile does + +- **A default of "off" ships a feature nobody has.** `connection_processes` + defaulted to 1, which starts no process: the multi-core path was measured at + 131 MB/s and reached by no node whose operator had not found the setting, so + on Windows a download over eight lanes landed on the node's one core and ran + at the speed of one connection. Worse, the Node page saved **every** setting + on each Save, so any operator who changed one thing had pinned all the others + at that day's defaults, in the roster and in `node.toml`. It sends only what + changed now, and `init` leaves the line commented. A test node that saved + its settings before this keeps `connection_processes = 1` until it is set + again on the Node page + +- **A reconnect let every message through, not just its handshake.** + `_inReconnectAttempt` opened `_sendAndWait` to all callers so the handshake + would not wait on itself; a chunk retry landing between the new channel's + open and the proof got "Handshake required", which no retry treats as a + dropped connection, and the download died with that text in the transfers + panel. Only the opening messages pass now (`SESSION_OPENING`, held to + `dispatch.py` by `test_reconnect_race.py`), and a replaced channel's late + `close` no longer clobbers the new one. `harness/reconnect_race_harness.mjs` + runs the real `connect()`, `_reconnectLoop` and pipeline against a node that + refuses before the proof — the first harness here that does; the earlier + ones stub `connect`, which is exactly where this lived + +- **A push handler that re-fetches the world.** The interactive CLI answered + every `index_delta` by fetching and re-parsing the whole index, on the event + loop that was receiving the download: 67 full indexes in 80 s while a node + enriched a library (one delta a second). It applies the delta in place + (`Tree.apply_delta`), and only a delta that adds or removes files asks again, + once per burst + ### More of the same, from four rounds of live testing - **A protocol harness cannot test the SPA.** Any second implementation of the |