12 KiB
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;它自身字节相同并不表示加载了同一库,
两臂分别从各自目录解析生产库。
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 重负载时运行;不占手机端口):
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 的归约逻辑。