diff --git a/docs/Disaggregated/MEASUREMENTS.md b/docs/Disaggregated/MEASUREMENTS.md index 6dfd6c15..36f47b98 100644 --- a/docs/Disaggregated/MEASUREMENTS.md +++ b/docs/Disaggregated/MEASUREMENTS.md @@ -15,7 +15,13 @@ 按形状实测(`RemoteClientControls.ReplyWaitsByOpForAnAtlasShapedLoad`,主机 inproc,按 op 计数):**图集拼接**(一张 level 上 64 次 `glTexSubImage2D`)**64 → 0** 次回包等待; **每 sprite 一张纹理**(64 张纹理 + 256 次 `glTexParameteri`)**384 → 320**,剩下的全是 per-resource / per-call 的三条 row(create 76 / respecify 130 / params 130)—— 它们的拒绝是「服务端没有这个 handle」的唯一客户端可见信号,删掉等待就是删掉信号,裁定见 `CONTRACT-P5E.md` §2.5。 - **真机端到端墙钟仍待复测**,见 [`notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md`](notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md)。 + 真机(TrebleDroid GSI,MC 26.2 经 TCP 入世界)那一帧的构成为 `ResourceRespecify` 20,633 + `SetTextureParams` 18,056 + `ResourceCreate` 4,536 条**各等一次**, + 而 `ResourceSubData` 12,671 条**零等待**(B 的实机证据);这些记录都是真实状态变化,客户端没有可去重的(同一值的 `glTexParameteri` 本来就不产生记录)。 +- **单次往返那 ~5 ms 是设备侧的深度空闲退出,不是链路也不是客户端**(P12,本轮实测):同一帧、同一批记录, + 客户端自旋 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 是在**未定频**的机器上取的,含这份空闲税。 + 见 [`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)。 ## 按阶段 diff --git a/docs/Disaggregated/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md b/docs/Disaggregated/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md index 61a8bf3c..4057825a 100644 --- a/docs/Disaggregated/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md +++ b/docs/Disaggregated/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md @@ -228,6 +228,29 @@ handoff §3.6 留过一个没解释的现象:把链路从 Wi-Fi 换到 USB( 而在「客户端 park → 服务端唤醒/读取/apply/回铃 → 客户端唤醒」这条本地路径上——这与两侧 profile 的形状一致(服务端 65% 在 socket syscall、约 15% 在门铃自旋)。 **结论:想动这一帧,只有两条路**——(a) 同样多的记录、更少的往返(把等待批起来,回复槽池 8 个 ⇒ K ≤ 8 可证明安全); (b) 降低单次往返的本地成本(服务端 apply/wake 路径、`MOBILEGL_IPC_SPIN_US` 之类)。**不是**换链路,也不是去重记录(§2.7 已证否)。 + +### 2.9 那 ~5 ms 的真身:**设备侧的深度空闲退出**(本轮把 handoff §3.6 的谜题解开了) + +§2.8 排除了链路,本节把剩下的候选一个个排除,最后落在一个可复现、可量化的原因上。同一台设备、同一份工作量(那一帧 43k 条记录),只改一个变量: + +| 变体 | 单次等待均值 `rtt_mean` | 那一帧的墙钟 | 说明 | +|---|---|---|---| +| 基线(LAN + 客户端 spin 50 µs + 设备出厂省电) | 5.0–7.9 ms | **221.5 s**(43,232 waits / 101.4 MB staged) | | +| 客户端 `MOBILEGL_IPC_SPIN_US=2000`(自旋 40×) | 4.8–6.9 ms | — | 只快 ~10% ⇒ **不是客户端 park/wake** | +| `adb forward`(USB,裸 RTT 低数倍) | ~25–30% 更快 | — | ⇒ **不是链路**(§2.8) | +| **设备 CPU 钉住**:8 核 governor→`performance`,关掉 `cpuoff_l`/`clusteroff_l`/`mcusysoff`/`s2idle` | **3,715 µs**(帧内均值从 5,040 降下来) | **166.5 s**(43,218 waits / 100.5 MB staged) | ⇒ **就是它**:同一条数、同样的字节,**快了 25%** | + +**机理**:服务端 apply 线程在两条记录之间 park,SoC 随即掉进 `cpuoff_l`/`mcusysoff` 这类深度空闲;下一条记录到达时要付**退出延迟**(毫秒级)。 +每一条记录一次唤醒 ⇒ 每次往返 ~5 ms,与链路无关(§2.8),也与客户端怎么等无关(自旋试验)。 + +**这同时解释了 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.10 于是「2–3 分钟停滞」的修法清单(按预期收益排序) + +1. **把等待批起来**(K ≤ 8,回复槽池可证明):同样多的记录、少得多的唤醒。与第 2 条互补,且**纯客户端**,不需要设备权限。 +2. **让服务端在记录之间保持"热"**:它自己的自旋预算(设备日志里的 `spin 50 us`)——但 APK 今天没有把 `MOBILEGL_IPC_*` 接进去(P12 阶段表里那条 "FCL env 与 plugin APK 开关表接线" 未做),所以真机上只能靠 root 钉频率来证明这块蛋糕有多大(本节已证明:25%)。 +3. **测量纪律**:任何 split 真机数字都应该在定频+关深度空闲的设备上取,否则把设备省电策略算进了"协议代价"。 ## 4. 证据位置 | 位置 | 内容 |