Measured on 2026-10-12. Test machine and receive-buffer diagnosis.
Release IPv4 loopback on the Mac mini M4 Pro: 16 clients, one context/one thread, no extra computation, 1 s measurement and 0.25 s warmup. Each dependency combination runs six payloads × three windows × three repetitions: 36 pass, 18 fail.
Cells show measured-phase lost echoes per run. All three repetitions have identical loss counts, and both dependency combinations match. Warmup errors remain in the raw JSON; failed configurations are excluded from throughput comparisons.
- Every payload passes at window 1, including 65,507 bytes. The 1,472-byte payload also passes at windows 16 and 64.
- At window 64, 8,192-byte messages lose 512 echoes per run; 16,356/16,357/16,384-byte messages each lose 767. The 65,507-byte payload loses 191 at window 16 and 959 at window 64.
Payload and MTU Limits
| Ordinary UDP payload | IPv4 | IPv6 |
|---|---|---|
| Protocol maximum | 65,507 = 65,535 − 20 − 8 | 65,527 = 65,535 − 8 |
| Without fragmentation at MTU 1,500 | 1,472 = 1,500 − 20 − 8 | 1,452 = 1,500 − 40 − 8 |
| Mathematical budget at MTU 16,384 | 16,356 | 16,336 |
These calculations assume a 20-byte IPv4 header or a 40-byte IPv6 base header and an 8-byte UDP header. IP options or extension headers reduce the budget; IPv6 jumbograms are outside this table. IPv6 routers do not fragment packets. These diagnostics use IPv4 only and do not establish IPv6 limits under load.
lo0 has MTU 16,384, but its IPv4 fragmentation/reassembly counters stayed
at zero even when larger datagrams succeeded. The mathematical MTU boundary
is not an observed fragmentation threshold on this loopback path. Cross-host
payload sizing must use the actual path MTU.
Kernel Evidence
| Dependency | Full socket buffers before → after | Increase | IPv4 fragmentation / reassembly increase |
|---|---|---|---|
| Standalone Asio | 89,059 → 112,837 | 23,778 | 0 / 0 |
| Boost.Asio | 126,672 → 150,450 | 23,778 | 0 / 0 |
Each dependency combination records 11,889 lost echoes in the measurement phase. The kernel counts cover the whole stage, including warmup, and are system-wide. They record receive-buffer overflow during the bursts; there is no recorded IPv4 fragmentation supporting fragmentation as the explanation for these losses. Send admission/completion and content errors are all zero.
The configured sockets report 64 KiB send / 4 MiB receive buffers.
net.inet.udp.maxdgram=9216 and net.inet.udp.recvspace=786896 stayed unchanged;
65,507-byte successful echoes show that 9,216 was not an effective payload
ceiling for these configured sockets. Window 16 passes at 16 KiB, while
window 64 overflows buffers: datagram validity and burst capacity are separate.
Reproduce
Compile using UDP build instructions, then run an independent C++ case:
build-perf/benchmarks/arknet_loopback_benchmark \
--protocol udp --payload 65507 --clients 16 --window 1 \
--io-model shared --io-threads 1 --work 0 --warmup 0.25 --seconds 1The archived Standalone command and kernel snapshots also retain the complete shell matrix and the Boost command. The optional offline chart tool needs the report environment:
build/report-venv/bin/python scripts/udp_limits_report.py \
--input-dir benchmarks/results/macmini-m4pro-20261012-udp/limits \
--output docs/performance/assets/udp-limits-loss.svgReport-tool checks validate the archived cohort and reject malformed data; they do not launch network tests:
python3 -m unittest discover -s scripts -p 'test_udp_limits_report.py' -vStandalone raw JSON · Boost raw JSON · Numeric chart data · Environment and measurement definitions
Source SHA-256: 0771574af8ca56f1914deb544b956079e0a2f24021953ded5f5d524e3df334b1.
See Buffers and flow control for the overflow explanation and configuration.