说明:这个实验目录里没有书面报告,只有脚本。本文是根据脚本代码以及项目交接文档中记录的运行结果整理的补记;凡是交接文档没有记下的数字,这里都不写。

摘要

项目的“战斗记录 App”(Battle Notes)在玩家打游戏时按截图键抓取游戏画面,交给路由器(router,把一张截图分给各个读取器的程序)读取,再由 SE(状态估计,把读到的观察累积成对局状态和对手构筑推断)生成“敌方推断”简报。单元测试只能分别检查这些部件,真正的问题常出在它们串起来之后。

这个实验做了一个端到端回放器:在离屏模式下启动真实的 App 代码——真实路由器、常驻的战场单位读取服务、真实的 SE 进程——唯一的替换是“截屏线程”改为按顺序返回测试局截图包里的下一张 PNG。对每张图按一次截图键,记录“按键 → 原图保存 → 路由结果保存 → 简报更新/稳定”的时间,最后把简报里的敌方英雄和敌方法术与该局真值对比。它后来成为每次发版前的门槛之一。

要回答的问题

  • 把真实 App 串起来以后,敌方英雄和敌方法术能否正确推断出来?会不会把我方法术误当敌方的?
  • 从按键到玩家看到简报更新要多久?
  • 有没有只在完整链路中才出现的卡死、崩溃或性能回退?

数据与来源

  • 测试池中的按时间顺序截图包,每包对应一局战斗(包内是该局按时间排序的截图和每张图的场景标签)。门槛通常使用 13 个测试局(其中包括晚间录像新增的 3 局),共 182 次按键。
  • 真值:测试局的精审对局真值(敌方英雄、敌方施放过的法术、我方法术),来自各包的审核文件。

方法

  1. 每局:用隔离的数据目录离屏启动 App,确认进入“手动战斗”输入模式,切到“敌方推断”页签。
  2. 可选:先等待路由器预热完成(模拟玩家在选秀阶段等待的几分钟),否则第一次按键包含约 20 秒的模型加载。
  3. 依次对包内每张图“按键”,等待原图保存、路由读取完成、简报任务和战场单位读取全部空闲,记录各阶段时间和每次简报更新时间。
  4. 若 App 的实时输入意外停止,记录错误信息和代码位置后结束本局,而不是对剩余每张图空等。
  5. 每局结束后立即销毁窗口再开下一局(之前留给垃圾回收时曾导致原生崩溃)。
  6. 评分:从最后一次按键后的简报中取“敌方英雄”和“敌方已施放”两行。英雄判为对/错/未知,并记录第几次按键首次判对;法术统计找到、漏掉,以及“误报”(简报中任何时刻出现过、但敌方从未施放的法术,例如我方自己的法术)。时延取“按键 → 简报稳定”的中位数和 p95。

配套脚本还包括:冷启动成本测量、运行期间每秒采样 CPU/内存/GPU 占用、各阶段时延统计,以及一组排查原生崩溃用的最小复现脚本。

设置

App 默认带“对游戏友好”的策略(较低进程优先级、限制线程数)。时延受机器负载影响很大;交接记录中凡是有并行任务的运行都注明“不作比较”。

结果

交接文档中记录的门槛结果:

运行 规模 准确性 时延
早期一版(rc7b) 10 局,126 次按键,0 失败 敌方英雄 10/10、法术 10/10、0 误报 按键到简报中位 4.8 秒、p95 6.7 秒(当时同时在跑录像扫描)
整体回归(10 月 9 日下午) 13 局,182 次按键,0 失败 英雄 13/13、法术 11/11、0 误报 简报稳定中位 3.22 秒、p95 4.57 秒(当时另一任务占用 GPU,不作比较)
RC14 门槛 13 局,182 次,0 失败 英雄 13/13、法术 11/11、0 误报 首次简报 p50/p95 2.12 / 3.30 秒;稳定 5.10 / 10.03 秒
RC15 门槛 13 局,182 次,0 失败 英雄 13/13、法术 11/11、0 误报 首次简报 p50/p95 1.92 / 4.61 秒(最大 6.63);稳定中位 4.57 / p95 9.75 秒

交接文档记录,敌方英雄 13/13、法术 11/11、0 误报在每次复测中保持不变。

失败与负结果

这个门槛的主要价值是抓到了只在完整链路中出现的问题:

  • 性能回退:一个候选版本第一次跑门槛就在某个测试局卡住——首次简报约 40 秒、稳定最长 103 秒。定位到新加的“敌方英雄栏组合搜索”每次刷新都跑满约 94 秒。修复(搜索 0.5 秒截停、缓存、超时先显示“还在推算”)后该局首次刷新 2.1 秒、之后 0.2 秒;那个版本作废,重建后重跑全部门槛。
  • 读到一半停止:回放用户一局真实对局时,App 在第 41 张图后停止输入。原因是每读一张就写一份回看快照,文件随读数增长超过 4 MB 写入上限,被当成致命错误。修复后同一局 44 张全部读完。
  • 原生崩溃:一次整体回归在第 12 局进程段错误退出,没有调用栈;加上崩溃栈记录后重跑第 12、13 局正常。后续用本目录的笔记本窗口生命周期压测复现:修复前约 60% 崩溃,最终定位到 Qt 列表项被删除时 Python 包装对象已先释放;修复后同样压测 8/8 不崩。
  • 有一次运行与录像扫描同时进行,用户反映游戏卡顿;此后约定游戏运行时只做轻量工作。

局限

  • 这是端到端回归门槛,只检查敌方英雄、敌方法术和误报三项,不是逐字段识别准确率,更不是商业游戏整体识别准确率达标的证明。
  • 13 个测试局反复用于门槛,不再是新的独立测试;截图包是人工挑选的截图,不等于实时自动选帧的覆盖。
  • 时延不含真实游戏画面抓取,结果受机器负载影响;交接记录指出,安静机器上的完整时延分解由后续实验(P135)测量。
  • 运行目录没有保存完整的 SE 结果,本文也没有原始报告,部分细节只能依赖交接记录。

结论与下一步

“只替换截屏、其余全真”的按键回放是一个简单而有效的门槛:准确性三项在各版本中保持满分,同时多次在发布前拦下了性能回退、存储错误和原生崩溃。它的局限在于评分项少、测试局固定;后续需要在测试池的新录像上复测,并与逐字段准确率评估配合使用。