Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

性能优化

性能优化是中级面试的高频区, 也是你的潜在主场: 风控 SDK 对体积 / 性能敏感, 你的经验比一般应用开发者更有说服力.

一, 性能方法论

性能问题先定义用户路径与指标, 再建立可比较的基线, 最后才改代码. 每个结论须包含设备/OS/构建, 场景, 样本量, 分位数与观测开销; 一次耗时, 平均值或 “感觉变快” 均不足以证明收益.

  1. 指标与基线: 定义里程碑和分母, 固定冷/温/热等场景, 记录 P50/P90/P95/P99 及环境.
  2. 归因假设: 将退化按主线程, 渲染, CPU, I/O, 锁, Binder, 内存或网络分类, 收集能证伪假设的证据.
  3. 最小改动: 只改变已定位路径的一个变量, 保留功能, 线程安全和失败降级.
  4. 验证: 在同基线复测分布, 并检查耗时没有转移到首次交互, 内存或电耗.
  5. 灰度与回滚: 在线上按版本 / 设备分群观察预设指标, 达到回退条件时关闭开关或回滚制品.
专项问题操作与完整案例
启动, TTID/TTFD, Splash, am start -W启动优化专项
Java/native/graphics 内存与 Heap Dump内存优化与泄漏排查
ANR, 帧, traces 和锁 / Binder 判断ANR 与卡顿排查
Perfetto, gfxinfo, simpleperf, Baseline Profile性能工具专题
线上采样, 符号化, 聚类和告警APM 与线上监控

总览章节边界

本章只维护 “指标 → 复现 → 定位 → 假设 → 最小改动 → 基线对比 → 灰度 / 回滚” 方法论. 专项内容分别见启动, 内存,ANR / 卡顿, 工具和线上监控. 具体阈值和工具步骤放在专项章, 避免多处维护过时数字.

方法论演练: 先测量, 再回滚

这是假设性教学案例, 不是实测结果. 发现某个用户路径退化时, 先定义该路径的起止指标和分母, 在相同设备, OS, 构建和场景下取得分位数基线; 再用适当证据提出一个可证伪归因假设. 一次只改一个已定位变量, 复测同一分布并检查没有把成本转移到其他路径, 内存或电耗. 最后以版本 / 设备分群灰度, 预先约定暂停放量和回滚条件. 启动, 内存, ANR, 工具和线上观测的具体操作分别见本章前述链接.

高频面试题

Q1: 如何开始一次性能优化? 先定义用户路径, 指标和分母, 建立可复现基线; 没有基线, 不应先改代码.

Q2: 如何从相关性走到归因? 写出可证伪假设, 收集线程, 渲染, I/O, 锁, 内存或网络证据; 单个慢方法或一次 trace 只能支持下一步调查, 不能单独证明因果.

Q3: 如何验证优化没有制造回归? 在原场景复测分布, 再检查关联路径, 功能正确性, 内存 / 电耗, 并按版本和设备分群灰度; 达到预设回退条件则关闭开关或回滚制品.

Q4: 优化在多个指标间冲突 (如启动更快但内存上涨) 怎么取舍? 先明确业务目标和可接受边界: 为关键路径设预算 (启动耗时预算, 内存预算), 收益按用户可感知指标量化, 成本按回归风险量化; 无法同时满足时按业务优先级取舍, 把取舍和测量证据写进方案记录, 不留无依据的 “平衡”.

Q5: 为什么不能只用平均值评估性能? 平均值掩盖长尾: 缓存命中, GC, 网络抖动会让 P99 远高于均值, 一次冷启动就能拉高整体耗时. 要看 P50/P90/P95/P99 与样本分布, 并固定场景 (冷/温/热, 低端机) 和环境; 具体采样方法见 性能工具专题.

Q6: 没有现成工具和基线时, 怎么开始一次性能排查? 先定义用户路径和可观测指标, 从系统自带能力 (dumpsys, am start -W, logcat, Perfetto) 收集分布; 复现问题路径后用二分定位到具体环节, 建立基线后再改代码. 顺序是 “先测量, 再假设, 最后最小改动”, 不是先改代码再补测量.

Q7: 性能优化和代码可维护性冲突怎么办? 优先优化已定位的热路径, 不牺牲抽象和可读性; 用注释记录优化原因和测量证据; 若优化依赖易碎假设 (版本行为, 厂商差异), 加兼容分支与回归测试并标注核验日期, 避免后续维护者无法回退.