mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
- 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".
6.0 KiB
6.0 KiB
实测(索引)
这一页只有结论和去向;完整的表、命令、协议与读法在各阶段
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 入世界)那一帧的构成为ResourceRespecify20,633 +SetTextureParams18,056 +ResourceCreate4,536 条各等一次, 而ResourceSubData12,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 的envextra →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 |