第1章 Java代码优化
依据Apress/O'Reilly与中文版完整目录覆盖16个节点:从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite
第1章 Java代码优化
本页依据Hervé Guihot《Pro Android Apps Performance Optimization》独立重构,不复制原文。原版锁定Apress 2012年1月版、282页、ISBN 9781430239994;中文版锁定人民邮电出版社2012年10月第1版、白龙译、226页、ISBN 9787115272416。
版本语境是Dalvik、Eclipse/ADT、Android 3.x至4.0、早期NDK与ARM/NEON,包含AsyncTask、TraceView、DDMS、layoutopt和RenderScript。课程先解释历史机制,再以ART、Benchmark、Perfetto、现代NDK与替代计算API建立迁移账本;不会把新工具倒填成原书目录。
学习目标
- 能解释“第1章 Java代码优化”全部16个正式节点的输入、正确性、执行边界、资源成本与2012年版本限制。
- 能实现“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的最小可重复实验,并保存源码、构建、设备、样本和原始测量。
- 能比较基线、优化、错误输入、设备差异和生命周期故障,分析“在没有等价性测试与基准的情况下微调语法,或用缓存换速度却不限制失效、容量和线程安全”。
- 能设计反例并凭算法基线、缓存命中、API分支、主线程违规、SQLite事务与查询计划完成独立复现与交接。
从正确性与测量协议开始
↡在相同输入、环境与可观察结果下代表优化前行为和资源成本的参照实现先于技巧。优化不能改变业务结果、线程安全、精度、生命周期或错误语义。每个实验先写输出断言和允许误差,再决定测量墙钟时间、CPU时间、分配、GC、唤醒、网络或帧;只取最快一次会系统性夸大收益。
↡规定设备状态、输入规模、预热、采样、统计和失败判据的可复现实验合同要控制构建类型、Android版本、ABI、CPU调频、温度、电量和后台负载。↡Java经JNI进入C/C++并承担数据转换、引用、异常、线程附着与ABI兼容的接口有固定成本,只有热点工作量足够大时,原生计算收益才可能覆盖跨界开销。
内存优化依赖↡让连续计算访问相邻数据并减少缓存未命中和不必要对象分配的布局性质,不只是“少用内存”。电池优化依赖↡一次功能允许消耗的CPU、无线电、定位、传感器、图形与唤醒总成本,减少一段CPU时间却增加网络唤醒并不一定更省电。
本单元主线是从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite。交互管线连接Java、JNI/NDK、内存线程、设备图形与用户结果;实验面板切换基线、优化、错误结果、热状态和生命周期;证据门要求正确性、时间、资源、设备和版本全部可重放。
权威目录逐节点映射
第1章 Java代码优化
正式节点 1/16。 “第1章 Java代码优化”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.1 Android如何执行代码
正式节点 2/16。 “1.1 Android如何执行代码”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.2 优化斐波纳契数列
正式节点 3/16。 “1.2 优化斐波纳契数列”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.2.1 从递归到迭代
正式节点 4/16。 “1.2.1 从递归到迭代”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.2.2 BigInteger
正式节点 5/16。 “1.2.2 BigInteger”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.3 缓存结果
正式节点 6/16。 “1.3 缓存结果”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.4 API等级
正式节点 7/16。 “1.4 API等级”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.5 数据结构
正式节点 8/16。 “1.5 数据结构”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.6 响应能力
正式节点 9/16。 “1.6 响应能力”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.6.1 推迟初始化
正式节点 10/16。 “1.6.1 推迟初始化”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.6.2 StrictMode
正式节点 11/16。 “1.6.2 StrictMode”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.7 SQLite
正式节点 12/16。 “1.7 SQLite”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.7.1 SQLite语句
正式节点 13/16。 “1.7.1 SQLite语句”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.7.2 事务
正式节点 14/16。 “1.7.2 事务”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.7.3 查询
正式节点 15/16。 “1.7.3 查询”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
1.8 总结
正式节点 16/16。 “1.8 总结”必须放进“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”的性能因果链:先固定输入与正确输出,再区分Java、JNI、原生、内存、线程、设备和图形边界,最后选择时间、分配、唤醒或帧证据。没有等价性测试和基线,任何更快数字都不能算优化。
为该节点准备未优化、优化和反例三组实现。固定设备、Android版本、ABI、CPU状态、构建类型与数据规模,完成预热和重复采样;记录原始结果、资源释放与回滚。现代工具可以重测,但必须单列与2012年机制的差异。
本章回顾
本页从“第1章 Java代码优化”覆盖到“1.8 总结”,共16个正式节点。掌握标准是能沿“从Dalvik执行、斐波纳契算法与缓存,扩展到API等级、数据结构、响应性、StrictMode和SQLite”解释执行与资源因果链,运行等价、边界和故障实验,并让另一位开发者凭算法基线、缓存命中、API分支、主线程违规、SQLite事务与查询计划重放结论。
练习
问题 1:“第1章 Java代码优化”覆盖哪些正式节点与性能主线?
问题 2:怎样建立本章最小可重复实验?
问题 3:本章最需要推翻的错误假设是什么?
问题 4:为什么一次更快数字不能证明优化?
问题 5:怎样迁移到现代Android而不改写原书?
问题 6:达到独立交接标准需要什么?
名词解释
本章出现的专业名词,用大白话再讲一遍。
- 性能基线
- 在相同输入、环境与可观察结果下代表优化前行为和资源成本的参照实现。
- 测量协议
- 规定设备状态、输入规模、预热、采样、统计和失败判据的可复现实验合同。
- 原生边界
- Java经JNI进入C/C++并承担数据转换、引用、异常、线程附着与ABI兼容的接口。
- 内存局部性
- 让连续计算访问相邻数据并减少缓存未命中和不必要对象分配的布局性质。
- 能耗预算
- 一次功能允许消耗的CPU、无线电、定位、传感器、图形与唤醒总成本。