src.nth.io/

summaryrefslogtreecommitdiff
path: root/main/stream_server.h
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2026-07-15 18:04:31 -0500
committerLuke Hoersten <[email protected]>2026-07-15 18:04:31 -0500
commit6ee12595d339eeafc7fdc7dbb9ba4c4c757f3565 (patch)
treef83470042963c24b2eef87b54d7d484ff0ca11be /main/stream_server.h
parent55303088ea499017c75203eef71588d18609f124 (diff)
stream: instrument TCP-window decomposition (wire kbps, hdr_gap, pend_age)
Before touching CONFIG_LWIP_TCP_WND_DEFAULT, make the window question decidable from the logs. New per-window metrics in the stream log, /state, and stats struct: - wire min/avg/max kbps: instantaneous throughput while each body drained (jpeg_len/recv_us). Ceiling ~= TCP_WND/RTT, so it scales with the window iff the window is the limiter. - hdr_gap min/avg/max us: time blocked waiting for the next header after finishing a body. Large = sender-paced; ~0 = receive path is the bottleneck. - pend_age min/avg/max us: publish->claim latency of painted frames. Growing across windows = queue backlog building, the failure mode that killed the previous WND=65535 attempt. Together with recv/dec/paint the frame interval is now fully decomposable: interval ~= hdr_gap + recv + pend_age + dec + paint. Also stamp TCP_WND/TCP_MSS/RECVMBOX into the client-connect log line so every capture is self-labeled with the config it ran under.
Diffstat (limited to 'main/stream_server.h')
-rw-r--r--main/stream_server.h16
1 files changed, 16 insertions, 0 deletions
diff --git a/main/stream_server.h b/main/stream_server.h
index e2eba06..2562738 100644
--- a/main/stream_server.h
+++ b/main/stream_server.h
@@ -73,6 +73,22 @@ typedef struct {
uint32_t last_paint_event_us_low; // last v1 frame's event_us_low,
// 0 if none seen yet on this
// boot or last frame was v0
+ // TCP-window decomposition. Together with recv/dec/paint these account
+ // for the whole frame interval:
+ // interval ≈ hdr_gap (sender idle) + recv (wire) + pend_age (handoff
+ // queue wait) + dec + paint.
+ // wire = instantaneous throughput while the body drained (jpeg_len /
+ // recv_us). Ceiling ≈ TCP_WND / RTT — the definitive window-throttle
+ // metric: scales with CONFIG_LWIP_TCP_WND iff the window is the limiter.
+ uint32_t wire_min_kbps, wire_avg_kbps, wire_max_kbps;
+ // Blocked-with-nothing-to-read time between previous body completion
+ // and next header completion. Large → sender-paced (we are NOT the
+ // bottleneck); ~0 → back-to-back arrivals, receive path is the limiter.
+ uint32_t hdr_gap_min_us, hdr_gap_avg_us, hdr_gap_max_us;
+ // publish → decode-claim latency of painted frames. Healthy: bounded
+ // well under a frame interval. Growing window-over-window = latency
+ // backlog building (the failure mode that killed the last WND raise).
+ uint32_t pend_age_min_us, pend_age_avg_us, pend_age_max_us;
} stream_server_stats_t;
void stream_server_snapshot_stats(stream_server_stats_t *out);