From ce0235b190db4825d2b103642edbc154f25e2c28 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 25 Sep 2026 20:17:22 +0800 Subject: [PATCH] [Docs] (P12): the three rows that keep their wait get a ruling with evidence behind it, and the handoff's open op-split question gets its numbers - What was open: the handoff's 4.3 called ResourceCreate and SetTextureParams "a second problem of the same kind, needing its own analysis" and left it there; 5.4 said the per-op split of the 55,428 waits was never quantified. The measurement committed beside this answers both. - The ruling (CONTRACT-P5E.md 2.5): ResourceCreate, ResourceRespecify and SetTextureParams stay kWaitReply, because each answer carries a fact about the SERVER's record table that the client's own tracker provably cannot know. RespecifyOnce says it outright - "the applier's REFUSAL is the only signal that says 'I hold nothing for this handle'", which is the scope MGPipeApplierReleaseObjectRecords leaves for a served context whose frontend objects live on; EmitTextureParams uses its own refusal as the same self-heal trigger; PublishCreate may not take the publication latch on a refused create (D-I1/c0b) or the death path emits a resource_destroy for a record that does not exist. Unlike the upload half these are not "the emission gate already answered it" rows, so removing their waits removes the signal. - The numbers, both shapes a stitcher produces: an atlas stitch goes 64 -> 0 reply waits; a texture per sprite goes 384 -> 320 with ResourceSubData now zero and the remainder all three of those rows. So item B hits exactly the shape it was aimed at, and what is left is per-resource / per-call rather than per-chunk. - notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md gains 2.4 with the table and the ruling, and its "second problem of the same kind" entry is closed rather than carried; MEASUREMENTS.md records the two shapes beside the 1 -> 0 single-upload number. --- MobileGL/MG_Remote/CONTRACT-P5E.md | 15 ++++++++++- docs/Disaggregated/MEASUREMENTS.md | 6 ++++- .../notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md | 26 +++++++++++++++++-- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/MobileGL/MG_Remote/CONTRACT-P5E.md b/MobileGL/MG_Remote/CONTRACT-P5E.md index ff9af16e..958edcd0 100644 --- a/MobileGL/MG_Remote/CONTRACT-P5E.md +++ b/MobileGL/MG_Remote/CONTRACT-P5E.md @@ -206,7 +206,20 @@ non-wire arm keep the old answer, which is what G1 measures. Gate: `RemoteClientControls.TextureUploadsStopOwningAReplyOnTheWireArm` reads back the same `wait_replies` the P65LinkMetrics line prints (`LinkMetricsReplyWaits`), asserting a pure upload moves it by ZERO while a `resource_create` row still moves it; red-once with the arm test removed is exit 142. -`ResourceCreate` and `SetTextureParams` stay `kWaitReply` — same question, asked per resource and +**`ResourceCreate`, `ResourceRespecify` and `SetTextureParams` stay `kWaitReply`, and that is a +ruling rather than an omission**: each one's answer carries a fact about the SERVER's record table +that the client's own tracker provably cannot know. `RespecifyOnce` (`TextureEmit.h:1332-1356`) says +it in one line - "the applier's REFUSAL is the only signal that says 'I hold nothing for this +handle'", which is the scope `MGPipeApplierReleaseObjectRecords` leaves behind for a served +context whose frontend objects live on; `EmitTextureParams` (`:991-1017`) uses its own refusal as +the same self-heal trigger; and `PublishCreate` (`:1303-1319`, D-I1/c0b) may not take the +publication latch on a create the applier refused, or the death path emits a `resource_destroy` for +a record that does not exist. Removing any of those waits removes the signal, so unlike the upload +half they are not "the emission gate already answered this" rows. Measured split for the two shapes +a stitcher produces (P12, `RemoteClientControls.ReplyWaitsByOpForAnAtlasShapedLoad`): an atlas +stitch - 64 sub-uploads into one level - goes from 64 reply waits to **0**, while a texture per +sprite - 64 textures, 256 `glTexParameteri` - goes from 384 to 320, with the remainder all three of +these rows (create 76, respecify 130, params 130). per call, analyzed separately rather than swept in here. ### 2.6 Event-ring flow control (ARCHITECTURE §11.7 made real) diff --git a/docs/Disaggregated/MEASUREMENTS.md b/docs/Disaggregated/MEASUREMENTS.md index 469c4e62..6dfd6c15 100644 --- a/docs/Disaggregated/MEASUREMENTS.md +++ b/docs/Disaggregated/MEASUREMENTS.md @@ -11,7 +11,11 @@ - **拆成两进程**:真机上与两线程成本持平;两者的 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"的那个计数器);**真机端到端墙钟仍待复测**,见 [`notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md`](notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md)。 + 单条纯上传占用的回包等待 **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)—— + 它们的拒绝是「服务端没有这个 handle」的唯一客户端可见信号,删掉等待就是删掉信号,裁定见 `CONTRACT-P5E.md` §2.5。 + **真机端到端墙钟仍待复测**,见 [`notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md`](notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md)。 - **画面正确**: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 53dd68e0..3749d505 100644 --- a/docs/Disaggregated/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md +++ b/docs/Disaggregated/notes/p12/DEVICELOST-AND-UPLOAD-WAITS.md @@ -94,6 +94,28 @@ DECLINED 有三条**完全不含损坏**的产生路径,两条在服务端、 其余改动全部落在 split-only 的翻译单元(`MG_Remote/**`)或 `PipeFill.cpp` 的 `#if MOBILEGL_BUILD_DISAGGREGATED` 块内。 因此 pull 臂预处理后与改动前**逐字符相同**。**本机已按 G1 跑过 A/B**:pull 配置(Release、`/usr/bin/c++`、`MOBILEGL_BUILD_DISAGGREGATED=OFF`、`--target MobileGL`)在 `c984d952`(基线)与 `3b9f536d`(本轮)各建一次,结果 `.text` **13872002 = 13872002** 字节、符号 **31746 / 31746**、**0 增 0 删**,逐符号 `comm` 无任何差异(两棵树留在 `build-g1-base/`、`build-g1-head/`,符号表在各自的 `syms.txt`)。 +### 2.4 「同类第二条」到底该不该等(handoff §4.3 末条 + §5.4) + +handoff §5.4 说「55,428 次等待里各 op 各占多少」未量化,§4.3 说 `ResourceCreate` / `SetTextureParams` 是同类第二条、"需单独分析"。本轮把两件事一起做了: +给 `LinkMetrics` 加了**按 op 的回包等待计数**(`LinkMetricsBeginReply(wantsReply, op)` / `LinkMetricsReplyWaitsFor(op)`,与总计数一样只在 `MOBILEGL_PIPE_STATS=1` 时记), +并用它量了拼接器会产生的两种形状(`RemoteClientControls.ReplyWaitsByOpForAnAtlasShapedLoad`,先打印后断言,好让红的那一次也留下数字): + +| 形状 | 没有 B | 有 B | +|---|---|---| +| **图集拼接**:一张 level 上 64 次 `glTexSubImage2D` | **64** 次回包等待 | **0** | +| **每 sprite 一张纹理**:64 张纹理 + 256 次 `glTexParameteri` | **384**(`ResourceSubData` 占 128) | **320**(`ResourceCreate` 76 + `ResourceRespecify` 130 + `SetTextureParams` 130,sub-data 0) | + +结论两条: + +1. **B 正好打在它要打的地方**:上传密集的形状(MC 的图集拼接就是这种)里,回包等待从「每次上传一次」变成 **0**——handoff §4.2 的预期在机制层面成立, + 与「96 MiB ÷ 32 MiB 窗口 ≈ 3 次等待」是同一件事的两面(剩下的是 stage 退休,不再是回包)。 +2. **剩下三个 row 不能照搬 B**,因为它们等的不是「你收下这批字节了吗」,而是**服务端的记录表里还有没有这个 handle**: + - `RespecifyOnce`(`TextureEmit.h:1332-1356`)原文:「the applier's REFUSAL is the only signal that says 'I hold nothing for this handle'」—— + served context 的 teardown(`MGPipeApplierReleaseObjectRecords`)会丢掉对象记录而前端对象还活着,这件事**客户端本地推不出来**; + - `EmitTextureParams`(`:991-1017`)用同一个拒绝做自愈触发器(context 的默认纹理就是这条路径救回来的); + - `PublishCreate`(`:1303-1319`,D-I1/c0b)不能在「被拒绝的 create」上落发布闩,否则死亡路径会为一个不存在的记录发 `resource_destroy`。 + + 所以这三条按 per-resource / per-call 结算,不是 per-chunk:**删掉等待就是删掉信号**。这条裁定已写进 `CONTRACT-P5E.md` §2.5。 ## 3. 本轮**没有**做的(下一轮的直接入口) 1. **真机端到端**:A 需要「进世界不再崩」、B 需要「那一帧墙钟 249 s → 约 20 s」的真机数字。需要重出 APK(`assembleTraceRelease` + 签名)、手机 `90cee93` 起 server、跨机 TCP 起 MC 26.2。 @@ -102,8 +124,8 @@ DECLINED 有三条**完全不含损坏**的产生路径,两条在服务端、 `launch-mc.py`(按版本 JSON 重建启动命令,已干跑校验:95 条 classpath 条目全部存在、Java 25 由 `javaVersion.majorVersion` 选出)、 `gl-aliases.sh`(把五个别名建在 `mgl-device/gl-aliases/`,**不放 build 目录**:那里的 `libEGL.so` 会让 server dlopen 自己)、 `start-phone-server.sh`(装包 + 起 Activity + handoff 那两个就绪判据)。 -2. **同类第二条**:`ResourceCreate` 与 `SetTextureParams` 也是逐条 kWaitReply(handoff §4.3 末条)。B 只处理了上传那半, - 这两条要单独分析(创建是按资源一次,参数设置是每次调用——收益与风险不同);`CONTRACT-P5E.md` §2.5 已把这一条写成 "analyzed separately"。 +2. ~~同类第二条~~ **已分析完毕(§2.4)**:`ResourceCreate` / `ResourceRespecify` / `SetTextureParams` 保持 kWaitReply 是有据的裁定, + 不是遗漏——它们的拒绝是「服务端没有这个 handle」的唯一客户端可见信号。**这条不再是待办。** 3. **主机门的环境前提**:本机 shell 沙箱没有 `/dev/dri`,所以任何需要真 EGL pbuffer 的车道(`SpawnLane.EventForfeitPeer`、`TcpLane.EventForfeitPeer`)在本会话里必然红(子进程 `kEglSurface = 12`),与本轮改动无关;`EventForfeitPeerTest.cpp:134` 的注释本来就写明这种 runner 会「every case reds before the ring ever fills」。 ## 4. 证据位置