Commit 54552bb
perf(tunnel): zero-copy mux + base64 off mux thread (#881)
Performance refactor of full-tunnel mode hot path. No wire-protocol or
behavior changes — internal data flow only.
**1. Zero-copy reads via `Bytes`/`BytesMut`**
`tunnel_loop` and the SOCKS5 UDP receive loop drop their per-iteration
`Vec::to_vec()` copies. `MuxMsg::{ConnectData,Data,UdpOpen,UdpData}` now
carry `Bytes` instead of `Vec<u8>`/`Arc<Vec<u8>>`; the `Arc::try_unwrap`
dance for `pending_client_data` is gone (Bytes is already Arc-backed).
TCP path is threshold-based to avoid the obvious memory regression:
- n ≥ 32 KB: `BytesMut::split().freeze()` — saves the 64 KB memcpy on
hot downloads.
- n < 32 KB: `Bytes::copy_from_slice` + `buf.clear()` — payload-sized
retention. Without this split, a queued tiny TLS record would refcount-
pin the full 64 KB recv buffer (worst case ~96 MB on a backpressured
tunnel).
UDP path: fixed `Vec<u8>` recv buffer + `Bytes::copy_from_slice` after
the 9 KB MAX_UDP_PAYLOAD_BYTES guard. `parse_socks5_udp_packet` split
into `_offsets` + `&[u8]` wrapper so callers stay on the reusable buffer.
**2. Base64 encoding moved off the single mux thread**
New internal `PendingOp { data: Option<Bytes>, encode_empty: bool }`
flows through `mux_loop` with raw bytes. Actual `B64.encode(...)` runs
in `fire_batch`'s spawned task, after the per-deployment semaphore. Up
to ~3 MB of encoding per batch (50 ops × 64 KB) no longer serializes
the single mux task.
**3. Code quality**
- `BatchAccum::push_or_fire` collapses 4× ~25-line match arms → ~10 each.
- `should_fire(pending_len, payload_bytes, op_bytes)` extracted with
`saturating_add` for a self-contained contract.
- `encode_pending(p) -> BatchOp` extracted as a free function so the
encoding contract is directly testable.
**Tests:** 208/208 (was 200, +8 new):
- `encode_pending_*` × 4 — base64-encode contract per MuxMsg variant
- `should_fire_*` × 3 — first-op, MAX_BATCH_OPS boundary, payload cap
- `batch_accum_reindexes_after_flush` — regression test for post-flush
reply index lookup in `fire_batch`
**Public API:** `TunnelMux::udp_open` and `udp_data` now take
`data: impl Into<Bytes>` instead of `Vec<u8>`. Existing call sites
keep compiling.
Reviewed via Anthropic Claude.
Co-Authored-By: dazzling-no-more <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 6249142 commit 54552bb
2 files changed
Lines changed: 469 additions & 162 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| |||
965 | 966 | | |
966 | 967 | | |
967 | 968 | | |
968 | | - | |
| 969 | + | |
969 | 970 | | |
970 | 971 | | |
971 | 972 | | |
| |||
991 | 992 | | |
992 | 993 | | |
993 | 994 | | |
994 | | - | |
| 995 | + | |
995 | 996 | | |
996 | 997 | | |
997 | 998 | | |
| |||
1118 | 1119 | | |
1119 | 1120 | | |
1120 | 1121 | | |
1121 | | - | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
1122 | 1131 | | |
1123 | 1132 | | |
1124 | 1133 | | |
| |||
1134 | 1143 | | |
1135 | 1144 | | |
1136 | 1145 | | |
1137 | | - | |
| 1146 | + | |
1138 | 1147 | | |
1139 | 1148 | | |
1140 | 1149 | | |
1141 | 1150 | | |
1142 | 1151 | | |
1143 | 1152 | | |
1144 | 1153 | | |
| 1154 | + | |
1145 | 1155 | | |
1146 | 1156 | | |
1147 | 1157 | | |
| |||
1162 | 1172 | | |
1163 | 1173 | | |
1164 | 1174 | | |
1165 | | - | |
| 1175 | + | |
1166 | 1176 | | |
1167 | 1177 | | |
| 1178 | + | |
1168 | 1179 | | |
1169 | 1180 | | |
1170 | 1181 | | |
| |||
1206 | 1217 | | |
1207 | 1218 | | |
1208 | 1219 | | |
1209 | | - | |
| 1220 | + | |
1210 | 1221 | | |
1211 | 1222 | | |
1212 | 1223 | | |
1213 | 1224 | | |
1214 | | - | |
| 1225 | + | |
1215 | 1226 | | |
1216 | 1227 | | |
1217 | 1228 | | |
1218 | 1229 | | |
1219 | 1230 | | |
1220 | 1231 | | |
1221 | | - | |
| 1232 | + | |
| 1233 | + | |
| 1234 | + | |
| 1235 | + | |
| 1236 | + | |
| 1237 | + | |
| 1238 | + | |
| 1239 | + | |
1222 | 1240 | | |
1223 | 1241 | | |
1224 | 1242 | | |
| |||
1292 | 1310 | | |
1293 | 1311 | | |
1294 | 1312 | | |
1295 | | - | |
| 1313 | + | |
1296 | 1314 | | |
1297 | 1315 | | |
1298 | 1316 | | |
| |||
1365 | 1383 | | |
1366 | 1384 | | |
1367 | 1385 | | |
1368 | | - | |
| 1386 | + | |
1369 | 1387 | | |
1370 | 1388 | | |
1371 | 1389 | | |
| |||
1473 | 1491 | | |
1474 | 1492 | | |
1475 | 1493 | | |
1476 | | - | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
1477 | 1508 | | |
1478 | 1509 | | |
1479 | 1510 | | |
| |||
1528 | 1559 | | |
1529 | 1560 | | |
1530 | 1561 | | |
1531 | | - | |
| 1562 | + | |
1532 | 1563 | | |
1533 | 1564 | | |
1534 | 1565 | | |
| 1566 | + | |
| 1567 | + | |
| 1568 | + | |
| 1569 | + | |
| 1570 | + | |
1535 | 1571 | | |
1536 | 1572 | | |
1537 | 1573 | | |
| |||
0 commit comments