Repository navigation
perf: optimize APK query pipeline - #5
Conversation
- Decode only class-query prefixes and detect late string pools before inflating full id tables. - Reuse worker inflate buffers/decoders and stream listings in deterministic order with bounded result retention. - Use compact locator maps, direct one-shot member queries and index-first reference candidate scans. - Make phase profiling opt-in; preserve CLI output and the list_classes string-row API. - Add regression coverage for query match modes, prefix layouts, record boundaries and DEX 041. Validation: cargo test --release --locked (79 tests), plus byte-identical outputs for 13 real-APK regression cases.
确定前缀再按需解压的实现很tricky,我很喜欢👍 |
概述
优化大型 APK 的
listclass、listmethod、findrefs查询管线,保持 CLI 输出和list_classes -> Result<Vec<String>, String>的库接口兼容性。本 PR 只有 1 个 commit,仅包含源码与回归测试;不提交 APK、性能报告、统计 JSON 或基准脚本。
主要实现
性能收益:相对 dev
基线为
24d3770;当前目标分支dev的7b72583仅增加合并提交,代码树与该基线一致。整体结果
按各用例的百分比降幅等权平均:耗时降低 23.65%,峰值物理占用降低 29.89%。这与“总耗时之比”和“平均峰值之比”的口径不同。
分用例
耗时为跨轮中位数,物理占用为每次进程采样峰值的跨轮中位数。
主要时间收益来自类列表和成员引用查询;listmethod 更主要的收益在内存。字符串引用查询和百分之零点几的耗时变化应视为基本持平,不宣称所有用例都显著加速。
淘宝退化的处理
最初的固定前缀阈值会在解完 id 表后才发现字符串区靠后,随后从头完整解压,导致淘宝 listclass 退化。简单改成剩余成本模型收益有限,未保留。
最终通过 DEX 头部附近的字符串偏移提示提前选择解码路径,同轮 dev/中间版/最终版为 31.21 / 34.50 / 29.12 ms。该偏移仅作为选择解码器的提示,不假定字符串物理顺序,不省略任何类,也不按 APK 名称特判。
测量方法与限制
https://,method 查询onCreate,field 查询mHandler,type 查询Landroid/util/。不将 getmanifest/getclass 计入收益。/dev/null;无输入预处理、持久化结果缓存或样本特判。ri_phys_footprint每 1 ms 采样,包含分配器保留等系统计费,不等同于活跃 Rust 堆或 RSS,极短峰值可能遗漏;RSS 另外通过wait4/ru_maxrss记录。验证
cargo test --release --locked:79 个测试通过。cargo test --release --locked --no-default-features --test listclass_api:4 个新增 API 测试通过。.gitignore、Manifest 或提交报告文件。建议 review 重点
前缀解析的异常数据/DEX 041 边界、缓冲区所有权、并发错误退出,以及 libdeflate 路径沿用的
unsafe输出缓冲初始化约束。现有解压路径仍有set_len后向解码器传递切片的安全债务,本次没有解决,合并前需要重点审阅;样本输出一致和测试通过不构成对任意畸形输入的安全证明。