From 6ee12595d339eeafc7fdc7dbb9ba4c4c757f3565 Mon Sep 17 00:00:00 2001 From: Luke Hoersten Date: Wed, 15 Jul 2026 18:04:31 -0500 Subject: 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. --- main/http_api.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'main/http_api.c') diff --git a/main/http_api.c b/main/http_api.c index 3774039..e64ebc9 100644 --- a/main/http_api.c +++ b/main/http_api.c @@ -118,6 +118,17 @@ static esp_err_t state_get_handler(httpd_req_t *req) cJSON_AddNumberToObject(s, "decode_idle_max_us", (double)stream.decode_idle_max_us); cJSON_AddNumberToObject(s, "last_paint_event_us_low", (double)stream.last_paint_event_us_low); + // TCP-window decomposition (see stream_server.h): wire = body-drain + // throughput, hdr_gap = sender idle, pend_age = handoff queue wait. + cJSON_AddNumberToObject(s, "wire_min_kbps", (double)stream.wire_min_kbps); + cJSON_AddNumberToObject(s, "wire_avg_kbps", (double)stream.wire_avg_kbps); + cJSON_AddNumberToObject(s, "wire_max_kbps", (double)stream.wire_max_kbps); + cJSON_AddNumberToObject(s, "hdr_gap_min_us", (double)stream.hdr_gap_min_us); + cJSON_AddNumberToObject(s, "hdr_gap_avg_us", (double)stream.hdr_gap_avg_us); + cJSON_AddNumberToObject(s, "hdr_gap_max_us", (double)stream.hdr_gap_max_us); + cJSON_AddNumberToObject(s, "pend_age_min_us", (double)stream.pend_age_min_us); + cJSON_AddNumberToObject(s, "pend_age_avg_us", (double)stream.pend_age_avg_us); + cJSON_AddNumberToObject(s, "pend_age_max_us", (double)stream.pend_age_max_us); cJSON_AddItemToObject(root, "stream", s); char *body = cJSON_PrintUnformatted(root); -- cgit v1.2.3