From 618395529fac0735c8ec4dea3a51ec90239b6245 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 25 Sep 2026 20:20:04 +0800 Subject: [PATCH] [Perf] (MG_Remote/Transport): the per-op reply-wait split also lands in the exit summary, because a spawn client never prints a frame line - The tally added beside this is only useful if somebody can read it where the problem is. The handoff says why that was hard: under spawn the client does not advance the frame window, so the per-frame P65LinkMetrics lines never print, and a SIGKILL takes the exit-time dump with it - "only the dump at exit, and SIGKILL does not get it". - LinkMetricsEnd writes the split on its own line from the one place a client that ends the ordinary way always reaches: P65LinkMetrics kind=per-op wait_replies=N by_op==,... . Ids stay raw (this file includes only and friends, not the op table) and the reader names them: 2 ResourceCreate, 3 ResourceRespecify, 47 SetTextureParams, 48 ResourceSubData. The mapping is written down in mgl-device/README.md, which is the page the device run reads. --- MobileGL/MG_Remote/Transport/LinkMetrics.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/MobileGL/MG_Remote/Transport/LinkMetrics.cpp b/MobileGL/MG_Remote/Transport/LinkMetrics.cpp index 35bc6f4b..a5da6b7d 100644 --- a/MobileGL/MG_Remote/Transport/LinkMetrics.cpp +++ b/MobileGL/MG_Remote/Transport/LinkMetrics.cpp @@ -111,6 +111,25 @@ void LinkMetricsPresent() { void LinkMetricsEnd() { if (!metrics.active) return; Emit("summary", metrics.total, ClockNs() - metrics.started, ThreadCpuNs() - metrics.cpuStarted); + // AND THE PER-OP SPLIT AT THE SAME INSTANT, on its own line. The handoff wanted this number + // and could not get it: under spawn the client does not advance the frame window, so the + // per-frame lines never print, and a SIGKILL takes the exit-time dump with it. The summary is + // written from the one place a client that ends the ordinary way always reaches. `op` is raw - + // this file does not include the op table - and the reader names rows with WireOpName. + char split[1024]; + std::size_t at = 0; + for (std::uint32_t op = 1; op < LinkMetricsMaxOps && at < sizeof(split); ++op) { + const std::uint64_t waits = metrics.total.waitRepliesByOp[op]; + if (waits == 0) continue; + const int n = std::snprintf(split + at, sizeof(split) - at, "%s%u=%llu", at == 0 ? "" : ",", + static_cast(op), + static_cast(waits)); + if (n < 0 || static_cast(n) >= sizeof(split) - at) break; + at += static_cast(n); + } + MGLOG_I("P65LinkMetrics kind=per-op wait_replies=%llu by_op=%s", + static_cast(metrics.total.waitReplies), + at == 0 ? "(none)" : split); metrics.active = false; } void LinkMetricsServerPresent(std::uint64_t serial) {