Files
cmautobuy/docs/task/109-量化领取到商品页耗时并消除重复设备检查.md

6.3 KiB

109 量化领取到商品页耗时并消除重复设备检查

背景与目标

Client 领取任务后到 PDD 商品页通常需要十几秒,但原代码没有分阶段耗时,且设备 连接已经读取一次 app_current() 后,采集和采购打开商品页又立即重复读取。

本任务建立不含业务数据的性能日志,量化 Admin、SQLite、ADB、uiautomator2 和 商品页阶段,并在不降低安全校验的前提下去掉同一会话内的重复检查。

最终方案

  • 新增轻量 TaskPerformanceTrace,使用单调时钟。任务调度器建立一次任务上下文, 设备和页面适配层在同一工作线程取得该上下文,不跨任务共享。
  • 正式启动时把 JSONL 写入 data/logs/task_performance.jsonl,按 2 MiB 轮转并保留 3 个旧文件。字段白名单只有 task_id、operation、duration_ms、result。
  • 计时覆盖 ADB 检查、Admin 领取、本地保存、uiautomator2 连接、首次应用状态、 PDD 启动/等待、打开链接、首次控件树、商品页就绪和端到端总耗时。
  • PddDeviceSession 保存连接时已经取得的应用状态。采集和采购打开商品页时复用该 瞬时结果,不再紧邻执行第二次 app_current()。
  • PDD 已由应用状态确认在前台时跳过固定 app_wait();需要启动时仍启动并等待。 打开链接后仍重新读取应用、控件树和商品页,验证码、风控、登录及采购门禁不变。
  • 显式 ADB 检查当前每轮只有一次,因此保留并计时,没有删除新鲜连接校验。
  • 新增只读真机测量工具,分别执行冷/热启动。工具不点击规格、下单或付款,遇到 登录或安全验证会停止。

实现与建单方案一致。额外增加独立测量工具,用于重复取得同环境中位数和 P95; 没有修改线程架构、Admin 接口、数据库、任务状态或 pdd_data。

真机测量与结论

同一台 Wi-Fi ADB 设备、同一商品页各执行 5 次。单位为毫秒,中位数 / P95:

阶段 冷启动 热启动
ADB 设备检查 16 / 16 15 / 15
uiautomator2.connect() 234 / 297 203 / 250
首次 app_current() 10593 / 10625 10578 / 10688
PDD 启动或等待 1016 / 1172 906 / 969
open_url() 110 / 140 157 / 188
首次 dump_hierarchy() 266 / 375 265 / 281
商品页就绪等待 2172 / 2281 2172 / 2266
端到端总耗时 14375 / 14516 14328 / 14422

嵌套阶段不能直接相加:商品页就绪包含控件树读取,端到端又包含全部阶段。这台 OPPO/ColorOS 即使 PDD 位于屏幕前台,app_current() 仍可能报告系统设置页, 所以热启动的启动/等待仍约 0.9 秒;控件树包名兜底继续保留。

原流程相邻调用两次 app_current(),本次按热启动中位数预计减少约 10.58 秒。 优化后 uiautomator2.connect() 仅 203 毫秒,约占端到端 1.4%,未达到 #110 的 2 秒或 20% 门槛。因此 #110 判定 No-Go,不实施持久 Device/QThread 重构。

改了哪些

  • client/src/performance_timing.py:性能上下文、白名单记录和轮转日志。
  • client/buyer_main.py:正式启动时初始化性能日志。
  • client/src/task_dispatcher.py:记录 ADB、领取和本地保存,并绑定任务上下文。
  • client/src/pdd_device_service.py:区分连接和首次应用状态计时,保存瞬时结果。
  • client/src/pdd_collect_service.py:复用首次状态并记录采集商品页阶段。
  • client/src/pdd_u2_purchase_adapter.py:复用首次状态并记录采购商品页阶段。
  • client/tools/measure_goods_open.py:安全的冷/热启动真机测量工具。
  • client/test/test_performance_timing.py:验证单调计时、任务隔离和日志白名单。
  • 相关设备、采集、采购和调度测试:验证冷/热启动、去重及安全行为。
  • docs/client/06-quality-security.md:记录日志字段、阶段、嵌套含义和测量方法。

验收结果

验收标准 结果
每次正式任务记录规定阶段和端到端耗时 通过
单调时钟非负、任务隔离,嵌套差异有文档解释 通过
日志使用四字段白名单,不包含控件树、URL、异常正文或凭据 通过
复用首次应用状态,PDD 已在前台时跳过固定等待 通过
设备、页面、安全页和采购门禁保持有效 通过
同环境完成 5 次冷启动和 5 次热启动 通过
#110 Go/No-Go 有数据依据 通过,No-Go
专项、Client 全量测试和语法检查通过 通过
未启用真实下单,未执行下单或付款 通过

测试

  • 执行的命令:
    • C:/Python310/python.exe -m pytest test/test_performance_timing.py test/test_pdd_device_service.py test/test_pdd_collect_service.py test/test_pdd_u2_purchase_adapter.py test/test_task_dispatcher.py -q
    • C:/Python310/python.exe -m pytest test -q
    • C:/Python310/python.exe -m unittest discover -s test -p "test_*.py"
    • C:/Python310/python.exe -m py_compile buyer_main.py src/performance_timing.py src/task_dispatcher.py src/pdd_device_service.py src/pdd_collect_service.py src/pdd_u2_purchase_adapter.py tools/measure_goods_open.py
    • C:/Python310/python.exe tools/measure_goods_open.py <设备号> <商品链接> --runs 5
    • git diff --check
  • 结果:专项测试 59 项通过;Client 全量 pytest 311 项通过;unittest 返回 OK; 语法和差异检查通过;真机冷启动 5 次、热启动 5 次完成。
  • 没验证到的部分:没有领取 10 条真实 Admin 任务,因此 Admin 请求和 SQLite 保存的真机端到端日志由 Mock/临时 SQLite 自动化测试覆盖;没有在真机上主动触发 验证码、风控或登录失效,仅由既有单元测试和 XML 固件覆盖;离屏主窗口能够创建 并输出 OK,但立即关闭时出现既有在线更新 Worker 的迟到回调警告,本工单未修改 在线更新或窗口关闭流程。

相关提交

  • ba0706d perf: 量化商品页打开耗时并去重检查 (#109)