[Fix] (Server): log the per-frame P65ServerFrame line only when MOBILEGL_SERVER_FRAME_STATS asks for it

This commit is contained in:
2026-10-03 14:20:11 -04:00
parent 0ef13ab0a6
commit 4633ca223c
3 changed files with 41 additions and 18 deletions
+39 -17
View File
@@ -28,6 +28,9 @@
#include <condition_variable>
#include <cstdlib>
#include <cstdio>
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#endif
#include <cstring>
#include <mutex>
#include <optional>
@@ -219,6 +222,23 @@ namespace MobileGL::MG_Remote::Server {
return text != nullptr && text[0] != '\0';
}
// The per-frame P65ServerFrame line is a measurement aid, not a log: at one line per present
// of every session it floods the device log (and pushes the lines tests grep for out of the
// ring). Opt in with MOBILEGL_SERVER_FRAME_STATS=1, or on Android the property
// debug.mobilegl.server_frame_stats=1; read once.
Bool ServerFrameStatsEnabled() {
static const Bool enabled = [] {
const char* value = std::getenv("MOBILEGL_SERVER_FRAME_STATS");
#if defined(__ANDROID__)
char property[PROP_VALUE_MAX] = {};
if (value == nullptr && __system_property_get("debug.mobilegl.server_frame_stats", property) > 0)
value = property;
#endif
return value != nullptr && value[0] != '' && value[0] != '0';
}();
return enabled;
}
void NameThisThread(const char* name) {
#if defined(__linux__) || defined(__ANDROID__)
pthread_setname_np(pthread_self(), name);
@@ -1099,23 +1119,25 @@ namespace MobileGL::MG_Remote::Server {
// reader spent WAITING for bytes, and one that is mostly recv calls with
// little read_ms is a reader that is copying.
const auto read = Transport::LinkMetricsTakeReadStats();
MGLOG_I("P65ServerFrame frame=%llu records=%llu apply_ms=%.1f wall_ms=%.1f "
"outside_ms=%.1f | read: %llu B in %llu recv(%llu reads) "
"recv_ms=%.1f total_ms=%.1f (%.0f%% blocked, %.1f MB/s)",
static_cast<unsigned long long>(++sFrameIndex),
static_cast<unsigned long long>(sFrameRecords), applyMs, wallMs,
wallMs - applyMs,
static_cast<unsigned long long>(read.bytes),
static_cast<unsigned long long>(read.calls),
static_cast<unsigned long long>(read.reads),
static_cast<double>(read.nsInRecv) / 1e6,
static_cast<double>(read.nsTotal) / 1e6,
read.nsTotal ? 100.0 * static_cast<double>(read.nsInRecv) /
static_cast<double>(read.nsTotal)
: 0.0,
read.nsTotal ? static_cast<double>(read.bytes) /
(static_cast<double>(read.nsTotal) / 1e9) / 1e6
: 0.0);
if (ServerFrameStatsEnabled()) {
MGLOG_I("P65ServerFrame frame=%llu records=%llu apply_ms=%.1f wall_ms=%.1f "
"outside_ms=%.1f | read: %llu B in %llu recv(%llu reads) "
"recv_ms=%.1f total_ms=%.1f (%.0f%% blocked, %.1f MB/s)",
static_cast<unsigned long long>(++sFrameIndex),
static_cast<unsigned long long>(sFrameRecords), applyMs, wallMs,
wallMs - applyMs,
static_cast<unsigned long long>(read.bytes),
static_cast<unsigned long long>(read.calls),
static_cast<unsigned long long>(read.reads),
static_cast<double>(read.nsInRecv) / 1e6,
static_cast<double>(read.nsTotal) / 1e6,
read.nsTotal ? 100.0 * static_cast<double>(read.nsInRecv) /
static_cast<double>(read.nsTotal)
: 0.0,
read.nsTotal ? static_cast<double>(read.bytes) /
(static_cast<double>(read.nsTotal) / 1e9) / 1e6
: 0.0);
}
sFrameWallStart = now;
sFrameApplyNs = 0;
sFrameRecords = 0;
+1
View File
@@ -173,6 +173,7 @@ MobileGL supports runtime configuration via environment variables.
| `MOBILEGL_ESPRYT_AVOID_SAMPLER_MIPMAP_MIN_FILTER` | Avoid sampler mipmap minification filters. | `0`, `1` | `0` |
| `MOBILEGL_COHERENT_AS_FLUSH` | Treat persistent `GL_MAP_FLUSH_EXPLICIT_BIT` maps as coherent (app-compat for engines like Flywheel that never flush them). | `0`, `1` | `0` |
| `MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION` | Always emulate depth/stencil `glReadPixels`/`glGetTexImage` by shader sampling on Espryt, instead of using the driver's own depth/stencil readback where it has one. | `0`, `1` | `0` |
| `MOBILEGL_SERVER_FRAME_STATS` | Log one `P65ServerFrame` timing line per presented frame on the server (apply vs. wall time, socket read rate). On Android also `debug.mobilegl.server_frame_stats`. | `0`, `1` | `0` |
| `VK_ICD_FILENAMES` | Select the Vulkan ICD used by the Vulkan loader. | Path to an ICD JSON file | Loader default |
## License
+1 -1
View File
@@ -95,7 +95,7 @@ P6.5 link numbers: `docs/Disaggregated/notes/p12/CROSSHOST-ACCEPTANCE.md`.
## netbench.sh — Wi-Fi TCP throughput baseline
**Understates the link**: the `toybox nc` sink capped at 18-22 MiB/s while the render server
read 52 MB/s on the same Wi-Fi. Use the server's `P65ServerFrame` read rate as the throughput number.
read 52 MB/s on the same Wi-Fi. Use the server's `P65ServerFrame` read rate as the throughput number (enable it with `MOBILEGL_SERVER_FRAME_STATS=1` or `setprop debug.mobilegl.server_frame_stats 1`; it is off by default).
WSL -> phone bulk transfer over `toybox nc` sink, 3 reps; refuses to run
unless `tcp_path_check.sh` passes. The `nc` listener must keep stdin open or it