[Docs] (P12): the server's spin budget is the portable half of the idle-exit fix - 221.5 s -> 182.8 s on the same frame, no root and no code change

- 2.9 established that a record's ~5 ms is mostly the DEVICE waking out of a deep idle state.
  That points at a knob that is already wired: how long the server's apply thread spins before
  parking. Raised from 50 us to 2000 us (via the Activity's existing `env` extra, which
  ServerEnvironment.apply parses as KEY=VALUE;KEY=VALUE and which does not scrub
  MOBILEGL_IPC_SPIN_US), the same 43,232-record frame goes 221.5 s -> 182.8 s (-17%), with
  rtt_mean 5,040 -> 4,145 us. Pinning the device and disabling its deep idle states is worth
  166.5 s (-25%) but needs root; the spin needs neither root nor a rebuild.
- The server log proves the knob landed (`mgl-srv-apply started ... spin 2000 us`) rather than
  leaving the reader to trust an env var, and the note carries the exact am start line.
- So the load stall now has three ordered levers with numbers behind them: batch the waits
  (client-only, not built), keep the server hot (this commit, usable today, trades device CPU for
  wall clock on a frame that is 94% waiting), and pin the device for measurement discipline.
This commit is contained in:
BZLZHH
2026-09-25 21:36:39 +08:00
parent 7c72dfde2b
commit c05e702d8c
2 changed files with 24 additions and 0 deletions
+2
View File
@@ -21,6 +21,8 @@
客户端自旋 40× 只快 ~10%;换 `adb forward`(USB)快 ~25–30%;而把设备 8 核钉 `performance` 并关掉 `cpuoff_l`/`clusteroff_l`/`mcusysoff`/`s2idle` 后,
单次等待 **5,040 → 3,715 µs**、那一帧墙钟 **221.5 s → 166.5 s(−25%)**——记录数与字节数都不变。
这解释了 handoff §3.6「换快 3.4 倍的链路墙钟不变」:钱花在设备每次唤醒上;handoff §3.2 那 249 s 是在**未定频**的机器上取的,含这份空闲税。
**同一个诊断给出一条可移植修法**:把服务端的自旋预算调大(Activity 的 `env` extra → `MOBILEGL_IPC_SPIN_US=2000`,不需要 root、不需要改代码),
那一帧 **221.5 s → 182.8 s(−17%)**;设备定频+关深度空闲则是 **166.5 s(−25%)**。服务端日志会打印 `spin 2000 us` 自证。
见 [`notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md`](notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md) §2.6–2.10。
- **画面正确**:Vulkan 后端真机画面检查 36/36 通过,CTS 五块相对基线没有超过 0.5 个百分点的退步、没有新崩溃(P7);server 自有窗口上屏两后端 SSIM 1.0(P12)。
@@ -246,6 +246,28 @@ handoff §3.6 留过一个没解释的现象:把链路从 Wi-Fi 换到 USB(
**这同时解释了 handoff 的两处观察**:§3.6「换快 3.4 倍的链路墙钟不变」(因为钱花在设备的唤醒上),以及 §3.3 服务端 profile 里那 65% 的 socket syscall / 15% 门铃自旋(等待与唤醒的形状)。
**也要说清楚**:handoff §3.2 那 249 s 是在**没有**做设备定频/关空闲的机器上取的(项目自己的纪律 `guide/pin-verification-2026-09-07.md` 就是为这件事写的),所以它的绝对值里含这份空闲税。
### 2.9b 同一个诊断的可移植修法:**服务端的自旋预算**(已实测,不需要 root、不需要改代码)
§2.9 的机理直接指向一个已经接好线的旋钮:服务端 apply 线程在记录之间 park 得越早,SoC 越容易掉进深度空闲。
本轮把它调大再测(同一台设备、同一帧、43,232 条记录、101.4 MB staged):
| 变体 | 最大帧 `rtt_mean` | 墙钟 | 代价 / 前提 |
|---|---|---|---|
| 基线(服务端 spin 50 µs,出厂省电) | 5,040 µs | **221.5 s** | — |
| **服务端 `MOBILEGL_IPC_SPIN_US=2000`** | 4,145 µs | **182.8 s(−17%)** | 设备侧多烧一点自旋 CPU;**不需要 root**、**不需要改代码** |
| 设备定频 + 关深度空闲 | 3,715 µs | **166.5 s(−25%)** | 需要 root/系统权限 |
`MOBILEGL_IPC_SPIN_US` 通过 Activity 现成的 `env` extra 传进去即可(`ServerEnvironment.apply` 的语法是 `KEY=VALUE;KEY=VALUE`,且它不在 `SCRUBBED` 名单里):
~~~sh
adb shell am start -n top.mobilegl.plugin.trace/top.mobilegl.plugin.MobileGLDisplayActivity \
--es listen tcp://0.0.0.0:40613 --es token <token> --es backend DirectGLES \
--es env "MOBILEGL_IPC_SPIN_US=2000"
~~~
服务端日志自己会证明它生效了:`mgl-srv-apply started … spin 2000 us`。**这条已经是可用的缓解手段**;要不要把它做成 Android 上的默认值(一行 env 或一个默认常量)是产品决定:
它拿设备 CPU 换墙钟,而这一帧本来就 94% 在等。
### 2.10 于是「2–3 分钟停滞」的修法清单(按预期收益排序)
1. **把等待批起来**(K ≤ 8,回复槽池可证明):同样多的记录、少得多的唤醒。与第 2 条互补,且**纯客户端**,不需要设备权限。