Files
MobileGL/docs/Disaggregated/MEASUREMENTS.md
T
BZLZHH 82ed1df90e [Perf] (MG_Pipe, MG_Remote/Client): a texture respecify for a CONFIRMED object stops waiting - the row pays its round trip once, at first use - and the frame drops from 130.9 s to 31.3 s
- The predicate is one function again: MGPipeResourceRespecifyWantsItsReply (PipeRoute.h) is read
  by the wire emitter, so the two halves of this row cannot disagree about whether an answer is
  owed. The buffer half never owes one (both call sites discard the Bool, PipeFill.cpp:1105/:1142);
  the texture half owes one exactly until MGPipeHandleIsPublished, and that latch is set only by an
  ACCEPTED create - which EmitResourceRespecify already sends, blocking, when it is clear
  (TextureEmit.h:869-879). So the object pays once, at first use, and every record after it is
  fire-and-forget.
- MEASURED on the device, same frame, same 101,421,396 B staged, stock power policy: waits
  25,154 -> 4,543 and wall 130.9 s -> 31.3 s. The op split is the proof of what changed and what
  did not: waits by_op 3=20611 -> absent (only 2=4536, 5=6, 9=1 remain), while the RECORDS sent
  are unchanged - frame-sent still shows 3=20633 and 103,094 records total. The round trips went
  away; the work did not.
- It also lands on an independent prediction: an audit run beside this work (mgl-device/scratch/
  scheme-review.md) computed 4,543 remaining waits and a 24-37 s credible range (midpoint ~30 s)
  from the archived logs, a host-inproc round trip of 35.4 us and a measured 43.1 MiB/s link.
  Measured: 31.3 s, at the midpoint.
- Cumulative on that frame since this work started: 43,232 waits / 221.5 s -> 4,543 / 31.3 s (7.1x).
  What is left is the create row (4,536 waits, ~23 s) - the confirmation itself, not waste - plus
  hard floors of ~13.4 s client CPU and ~2.2 s of transfer. Going below that means batching the
  create row, which keeps real answers.
- TWO DEBTS, STATED: (1) the invalidation guard for the one silent-loss case is NOT wired; the
  audit confirmed independently that no production path can drop a texture record today, and if
  one appears the notice it needs is protocol-surface (a tenth reverse callback). (2) No SSIM or
  visual check has been taken since these rows stopped asking - frame-sent agreement is strong
  evidence but it is not a picture.
- Two stale controls in older cases were fixed rather than left: the item-B gate now names the
  CREATE row (its old total-based control only moved because a respecify was still waiting), and
  the by-op measurement asserts records-sent for the rows that deliberately stopped waiting.
  RemoteClientTest 169/169; red-once for the predicate is forcing it back to "always wait".
2026-09-25 23:29:08 +08:00

6.0 KiB
Raw Blame History

实测(索引)

这一页只有结论和去向;完整的表、命令、协议与读法在各阶段 notes/<阶段>/README.md 的"实测"节。代码和旧笔记里的 MEASUREMENTS.md §N 按下表"§"列找到对应阶段(小节编号在那里原样保留)。

口径:性能只记录、不设门;看逐线程 CPU 时间,不看整机帧率。性能对比只用一台手机(Redmi 2f7cbe2e,Adreno 830),定频、同热窗口、两臂交替跑(guide/pin-verification-2026-09-07.md)。

关键结论

  • 接口本身的代价:单进程里改成"前端推、后端收",CPU 多约 6–12%(P2),已接受;顶点数组切换密集的场景更高(P3a,+27–30%)。
  • 拆成两线程:起初游戏里只有 7–13 fps;优化后 103–106 fps(P5d);client 发完就走以后,重负载(渲染距离 32)下与单线程持平(P5e)。
  • 拆成两进程:真机上与两线程成本持平;两者的 GL 线程 CPU 都比单线程少约 30%(后端工作挪到了另一线程 / 进程)(P6)。
  • 跨机:电脑经 TCP 连手机,102 个集成用例全过;server 被杀后 133 ms、Wi-Fi 断开后约 5 s 干净报"设备丢失"(P6.5)。
  • 纹理上传的等待粒度(P12,handoff §4):wire 臂上纹理那半 resource_subdata 不再逐条买回包,等待点从「每条记录」落到「SEG_STAGE 窗口用尽」。 单条纯上传占用的回包等待 1 → 0(wait_replies,正是 §3.2 里"一帧 55,428"的那个计数器)。 按形状实测(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)—— 这两条后来被"首次使用确认"取代了(见下面那条):对象的存在性由它自己的 create 确认为事实之后, params 与 texture respecify 都不再逐条买答案,而是只在首次使用时付一次阻塞的 create。 同一帧的累计实测:43,232 waits / 221.5 s → 4,543 waits / 31.3 s(7.1×),staged 字节与发出的记录数(103,094)都不变。 真机(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 是在未定频的机器上取的,含这份空闲税。 同一个诊断给出一条可移植修法:把服务端的自旋预算调大(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 §2.6–2.10。
  • 画面正确:Vulkan 后端真机画面检查 36/36 通过,CTS 五块相对基线没有超过 0.5 个百分点的退步、没有新崩溃(P7);server 自有窗口上屏两后端 SSIM 1.0(P12)。

按阶段

§ 阶段 一句结论 全文
1 P0 能从应用进程拉起第二个进程;跨进程共享 GPU 内存只有一条路在所有设备上可用 notes/p0
2 P1 逐 draw 核对推送状态,79 条 trace 零分歧 notes/p1
3 P2 桌面基准:新 tracker 比它替掉的旧填充更便宜 notes/p2
4 P3a 两机真机 Release:接口代价 +6–12%,VAO 切换密集的场景 +27–30% notes/p3a
5 P4a 换到 Redmi;P4a 自己只加 3–6 个百分点 notes/p4a
6 P5 两线程第一帧画对;真机两线程臂还跑不完 notes/p5
7 P5b 真机两线程跑通四条游戏 trace;两线程额外代价 +6–18% notes/p5b
8 P5c 两线程之间零共享内存后,全部测试仍绿 notes/p5c
9 P5d 游戏内 7–13 → 103–106 fps,client CPU 15.0 → 9.2 ms/帧 notes/p5d
10–11 P5e 发完就走比每条都等快 69%;重负载下与单线程持平 notes/p5e
12 P6 两进程与两线程持平;每帧数据量与记录数首次实测 notes/p6
13 P3b/P4b 纹理上传形状在四种拓扑下完全一致 notes/p34b
14 P6.5 跨机 TCP 102/102;断线约 5 s 检测到 notes/p65
15 P7 真机画面 36/36;server 内存无界增长收住(主机 825 → 546 MiB) notes/p7
16 P12 审查后真机复测:Espryt SSIM 1.0;Magma 1.0 / 0.999999511;P12 定向 CTest 46/46;纹理上传回包等待 1→0(主机机制门,真机墙钟待测);FCL 与跨机 TCP 收官门仍待完成 notes/p12