6.3 KiB
6.3 KiB
109 量化领取到商品页耗时并消除重复设备检查
- 类型:重构
- 父级大工单:#1
- 所属 MVP / 版本:MVP 后续 / 任务执行性能优化
- 状态:已完成,用户验收通过
- 日期:2026-08-10
- Gitea 工单:http://ilaer.eicp.net:8418/chengma/cmautobuy/issues/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 -qC:/Python310/python.exe -m pytest test -qC:/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.pyC:/Python310/python.exe tools/measure_goods_open.py <设备号> <商品链接> --runs 5git diff --check
- 结果:专项测试 59 项通过;Client 全量 pytest 311 项通过;unittest 返回
OK; 语法和差异检查通过;真机冷启动 5 次、热启动 5 次完成。 - 没验证到的部分:没有领取 10 条真实 Admin 任务,因此 Admin 请求和 SQLite
保存的真机端到端日志由 Mock/临时 SQLite 自动化测试覆盖;没有在真机上主动触发
验证码、风控或登录失效,仅由既有单元测试和 XML 固件覆盖;离屏主窗口能够创建
并输出
OK,但立即关闭时出现既有在线更新 Worker 的迟到回调警告,本工单未修改 在线更新或窗口关闭流程。
相关提交
ba0706dperf: 量化商品页打开耗时并去重检查 (#109)