Files
MobileGL/docs/archive/notes/p65/performance.md
T

185 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P6.5 主机逐线程 CPU 前后记录
**已经取得前后数字,但不能称为“逐字不变”。** 本次记录覆盖本机 inproc 与 unix+shm spawn,
用于观察整波改动对保留车道的影响;性能按路线图通用纪律只记录,不据此阻塞正确性验收。
它不代表 TCP 吞吐,也不代表 Android Release 性能。
## 定义与条件
- WSL Arch、DirectGLES + llvmpipe;两臂均使用现有 Release 制品,同一个 retrace 可执行文件。
- before:`/home/swung/lk-split/libMobileGL.so`;after:READY6 的
`/home/swung/p65-split/libMobileGL.so`。各自启动同目录下的 server。
before 是既存的 P6.5 前制品,以实际 SHA-256 定身份;旧 CMake 缓存中的 build stamp
不足以声称它恰好对应当前远端源码头。
- OpenRA 完整 trace 128 帧,选择最后 **100 帧**;rd12 in-world 完整 trace 251 帧,选择最后 **200 帧**。
均排除起始资源准备窗口,不把全部 replay 时间除以帧数充作稳态结果。
- 每个 case × transport × before/after 均为 **3 次完整 replay**,共 24 个样本。
每组记录按 repeat 交替 inproc/spawn;全部 before 完成后等待构建结束,再采 after。
不是版本间随机交错试验,也没有 CPU 定频,因此不据此宣称统计显著性或唯一因果。
- 采集窗口内没有并发重型构建或另一条 host retrace。此前带
`before-pilot-not-comparable` 标签的试跑仅用于校验采集器,不进入表格。
- `PRESENT_CREDIT=1`、run-ahead=1、verb-barrier=1、batch-waits=1、spin=50us;
PipeStats=0、strict=0、role-split-state=0、audit=0。完整有效环境随每条样本保存。
- `--benchmark-finish=0`:runner 不额外在每帧插入 glFinish;trace 自己的同步行为仍保留。
**client CPU** 来自已有 runner 的 `CLOCK_THREAD_CPUTIME_ID` 与 `frameCpuTimesMs`,
取选中尾窗口的平均值。它包括该 replay 线程上的解码与 MobileGL 调用,不是整个进程 CPU,
也不是只计 MobileGL 函数的采样 profile。
**apply CPU** 来自 `/proc/<pid>/task/<tid>/schedstat` 的 execution runtime 纳秒计数。
选择最早的、仍存活的 `mgl-srv-apply` TID;后建的 driver helpers 会继承该名字,不能相加冒充
一个 apply 线程的 CPU。每条原始采样保留 pid、tid、线程名、采样时刻和累计 CPU。
如果没有唯一线程完整覆盖选中窗口,采集器报无效,不填 0。
### apply 窗口的精度限制
runner 现有帧数组没有绝对 monotonic 起点,因此外部 apply 采样使用 benchmark JSON 的文件 mtime
近似定位 `benchmark::End()`,再减去已有 `totalSeconds - sum(frameTimesMs)` 的非帧尾段,
最后回退选中尾窗口的 wall 时间。两个边界在线程 CPU 采样点间线性插值。
这存在**未单独测量的 summary/JSON 序列化延迟**,不能写成严格帧边界同步或纳秒精度的结果。
请求采样周期为 5 ms;before 实际最大间隔 **7.159784 ms**,after 为 **15.230268 ms**。
实际间隔与原始点均保留,后续可重新归约。下面多保留的小数位用于复算,不提高测量精度。
## 结果
每项是三次 replay 的“尾窗口 CPU 均值”的中位数,单位 **ms/帧**。
百分比为 `(after / before - 1) × 100`;完整未舍入值在 comparison JSON 中。
| trace | transport | 线程 | before | after | 差值 ms/帧 | 差值 % |
|---|---|---|---:|---:|---:|---:|
| OpenRA | inproc | client | 0.681840 | 0.705350 | +0.023510 | +3.448023% |
| OpenRA | inproc | apply | 3.040668 | 3.108000 | +0.067333 | +2.214402% |
| OpenRA | spawn | client | 0.806240 | 0.786330 | -0.019910 | -2.469488% |
| OpenRA | spawn | apply | 3.242036 | 3.198453 | -0.043583 | -1.344321% |
| rd12 | inproc | client | 8.287390 | 8.362680 | +0.075290 | +0.908489% |
| rd12 | inproc | apply | 64.884249 | 64.917254 | +0.033006 | +0.050868% |
| rd12 | spawn | client | 10.276510 | 10.285330 | +0.008820 | +0.085827% |
| rd12 | spawn | apply | 67.614988 | 67.059490 | -0.555499 | -0.821561% |
逐轮均值的范围也必须保留,避免只给一个点:
| trace / transport / 线程 | before 三轮范围 | after 三轮范围 |
|---|---:|---:|
| OpenRA / inproc / client | 0.678730–0.688320 | 0.690650–0.715600 |
| OpenRA / inproc / apply | 3.038111–3.112060 | 3.064185–3.172090 |
| OpenRA / spawn / client | 0.799590–0.810700 | 0.780370–0.792480 |
| OpenRA / spawn / apply | 3.239807–3.299042 | 3.187598–3.211357 |
| rd12 / inproc / client | 8.195700–8.325585 | 8.311060–8.510350 |
| rd12 / inproc / apply | 64.826829–64.939705 | 64.915537–65.039914 |
| rd12 / spawn / client | 10.274680–10.279320 | 10.250475–10.306380 |
| rd12 / spawn / apply | 67.489521–67.649413 | 67.010901–67.281044 |
存在双向变化:inproc client 的两个样本组上升,spawn client 一降一基本持平;
apply 也不完全相同。没有删除正增量,没有扩大阈值把它改写成“零开销”。
整波还补齐了独立 client 的死亡记录等正确性行为,故不能把全部差值唯一归因于 lk2 的调用形式。
## 制品与复现
共同 runner:
`/home/swung/tr-split/tools/trace_replay/mobilegl_trace_replay`
| 制品 | SHA-256 |
|---|---|
| runner(前后相同) | `700907be83c2c1c1c83eec8de37300a6fdab4c7f06387116fa8aaee0169b7291` |
| before libMobileGL.so | `a84d0c09b78b312c600e172c03bd9a6e4ce804585661859d888b20992b4e516d` |
| after libMobileGL.so | `d783080c5e1cb7db209a362db4ad742634d7525ae0c9683c4f6e9c5c54803361` |
| server launcher(前后相同) | `7a95cb4d276b40e4843c9d9f8c4d0f3486bfa6b5fc3e3b9a0dd842e1e9403ed6` |
server 是薄 launcher,`NEEDED libMobileGL.so`、`RUNPATH=$ORIGIN`;它自身字节相同并不表示加载了同一库,
两臂分别从各自目录解析生产库。
```bash
python3 <tree>/tools/trace_replay/measure_transport_cpu.py \
--runner /home/swung/tr-split/tools/trace_replay/mobilegl_trace_replay \
--library /home/swung/lk-split/libMobileGL.so \
--server /home/swung/lk-split/libMobileGLServer.so \
--fixtures /home/swung/w7/pipe/tools/trace_replay/fixtures \
--inputs /home/swung/p65-host-cpu-input \
--out /home/swung/p65-host-cpu-before --label before-p65 --repeats 3
```
after 只将 library/server 换成 `p65-split` 目录,out/label 换成对应 after 名。
脚本拒绝覆盖已存在的 benchmark 证据;重新测量应换新的 out。
新工作树中的某些 fixture 是 LFS 指针,故本次使用已核实的 Linux fixture 实体,并保存每条 trace SHA-256。
证据位置:
- `/home/swung/p65-host-cpu-before/summary.json`
- `/home/swung/p65-host-cpu-after/summary.json`
- `/home/swung/p65-host-cpu-comparison.json`
- 各目录的 `<transport>/<case>/run-N/{benchmark.json,cpu-summary.json,apply-samples.json,runner.log}`
这些数关闭了“必须真的量到逐线程 CPU”这一记录缺口,不关闭其他尚缺的 P6.5 设备/trace/吞吐指标,
也不把性能变化当正确性失败。
## 当前 spawn 与 loopback TCP 的专门比较:首轮负控
另外启动了仅用于本机测量的 `tcp://127.0.0.1:40616` supervisor,使用当前库、同一 runner、
credit=1,client/server 均开启 `MOBILEGL_PIPE_STATS=1`、`MOBILEGL_PIPE_STATS_PERIOD=1`。
`measure_loopback_cpu.py` 用 `P65LinkMetrics` 与 `P65ServerMetrics` 的线程 CPU 时钟,
逐个核对 client/server 帧号:OpenRA 29–128(100 帧),rd12 52–251(200 帧)。
这组 apply 数据直接来自帧时钟,不使用上节的 `/proc` 外部窗口近似。
**首轮不能作为纯传输成本对照。** 虽然两臂都请求 run-ahead=1,实际日志证明 spawn 已 ARMED,
而 TCP 在真实第一份 CapsSnapshot 到达之前,错误地用 placeholder 的零能力锁存为 lockstep,
随后“只允许 demotion”的规则使它一直无法武装。该差异由真实测量揭露,不能当成 TCP 固有成本放过。
完整首轮样本保留在 `/home/swung/p65-loopback-cpu/summary.json` 与
`summary-with-arm-proof.json`;OpenRA 每臂三轮,rd12 每臂一轮。
其中 rd12 的实际 client/apply CPU 为 spawn **10.377163 / 66.994613 ms/帧**,
错误 lockstep 的 TCP **105.151038 / 160.624839 ms/帧**。
这是具名负控证据,不进入正式 transport 比较结论。
修复由启动路径等待真实首 caps 完成,不强制打开 run-ahead,也不放宽后续只允许 demotion 的规则。
采集器已增加实际 ARMED、无 lockstep fallback、无 DISARMED 的检查;下节记录修复制品的正式重跑。
### 首 caps 修复后的正式两角色 CPU 数
修后 TCP 已完整重跑,所有样本均通过实际 run-ahead ARMED 检查,没有 fallback 或 DISARMED。
OpenRA 各臂 3 次取逐轮均值的中位数;rd12 各臂 1 次,单次样本不用于统计显著性推断。
两角色使用相同精确帧号窗口,不把 setup 算入稳态,也没有使用外部 `/proc` 插值。
| trace / 窗口 | 线程 | spawn unix+shm ms/帧 | TCP+stream ms/帧 | TCP − spawn ms/帧 | 差值 |
|---|---|---:|---:|---:|---:|
| OpenRA / 29–128 | client | 0.913889030 | 0.725938440 | -0.187950590 | -20.566019% |
| OpenRA / 29–128 | apply | 3.414349090 | 3.123573070 | -0.290776020 | -8.516294% |
| rd12 / 52–251 | client | 10.377163490 | 6.507507265 | -3.869656225 | -37.290115% |
| rd12 / 52–251 | apply | 66.994613060 | 53.903945275 | -13.090667785 | -19.539881% |
这是**指定两个线程**的实测变化,不能据负差值宣称 TCP 的进程总 CPU 更低:
TCP 另外有专用 I/O reader,以上 client/apply 时钟不包含那些线程的 CPU,也不包含其它 driver workers。
本表开了 PipeStats,前节 P6.5 前后表关闭 PipeStats;两表不能交叉相减。
spawn 控制复用本轮首 caps 修复前已真实 ARMED 的样本,其运行中的数据路径未改变;
TCP 使用修后制品。这个复用边界明确保留,不称两个 library 文件哈希相同:
- spawn library:`d783080c5e1cb7db209a362db4ad742634d7525ae0c9683c4f6e9c5c54803361`
- TCP library:`29fcff6b23557be6b1cc3765db382b3422ed0780643c719937616259298d3116`
- runner 与输入 trace 保持相同,完整哈希在各样本 `role-cpu.json` 中。
并发检查:最后一项 syntax 编译结束于 WSL 07:56:32.732;TCP OpenRA 三轮尾窗口分别从
07:56:56、07:56:58、07:57:00 开始,rd12 尾窗口从 07:57:55 开始,均无编译重叠。
这组精确帧时钟证据为 `/home/swung/p65-loopback-cpu-fixed/summary.json`,
归约比较为 `/home/swung/p65-loopback-cpu-comparison.json`;旧 lockstep 数据仍原样保存为负控。
最小复现(在没有其它 host 重负载时运行;不占手机端口):
```bash
p65_tree=/mnt/c/Users/geekerwan/.codex/worktrees/p65-all-tcp/MobileGL
LIBGL_ALWAYS_SOFTWARE=1 EGL_PLATFORM=surfaceless \
MESA_GL_VERSION_OVERRIDE=3.3 MESA_GLSL_VERSION_OVERRIDE=330 \
python3 "$p65_tree/scripts/ci/tcp_server_fixture.py" start \
--server /home/swung/p65-split/libMobileGLServer.so \
--endpoint tcp://127.0.0.1:40616 --state /tmp/p65-cpu-server.json
trap 'python3 "$p65_tree/scripts/ci/tcp_server_fixture.py" stop --state /tmp/p65-cpu-server.json' EXIT
python3 "$p65_tree/tools/trace_replay/measure_loopback_cpu.py" \
--runner /home/swung/tr-split/tools/trace_replay/mobilegl_trace_replay \
--library /home/swung/p65-split/libMobileGL.so \
--server /home/swung/p65-split/libMobileGLServer.so \
--inputs /home/swung/p65-host-cpu-input --out /tmp/p65-role-cpu
```
该命令用同一当前制品重测两臂;本次修复后仅 TCP 重测使用了 `--transport tcp`。
脚本按帧号核对两份日志、拒绝缺帧/重复帧/非正 CPU,并复用 `p65_link_metrics.py` 的归约逻辑。