重构与性能的次序原则
先让代码正确且清晰,再针对已知热点做性能优化。性能问题要用度量定位而不是猜——profiler 通常会指出少数几处瓶颈,与直觉猜测的位置往往不同。重构一般不会改变性能的数量级;确实担心时,用基准测试在改动前后各测一次,把猜测换成数据。
基本信息
| 次序 | 正确性 → 清晰性 → 性能 |
|---|---|
| 手段 | profiler 定位热点、基准测试对比前后 |
| 边界 | 已确认的热点路径可暂缓重构,但要留下标记 |
| 原则 | 先度量后优化,避免为想象中的性能牺牲可维护性 |
推进方式
- 先补齐测试,确保重构期间行为可比对
- 用 profiler 采样找出真实热点,而不是从最丑的代码开始
- 热点之外照常重构:绝大多数代码的性能余量足够
- 热点内部若必须保留低可读写法,加注释说明原因与数据
- 改动前后各跑一次基准,把结果写进 PR 描述
- 基准要控制变量:同一机器、同一数据规模、多次运行取中位数
度量小抄
度量小抄
Linux: perf stat / perf record -g
Java : async-profiler、JFR(jcmd <pid> JFR.start)
JS : node --cpu-prof、Chrome Performance 面板
Go : go test -bench、pprof(net/http/pprof)
# 基准对比要点
- 固定数据规模与机器,多次运行取中位数
- 对比改动前后的同一指标,别只报改善的那一项常见误区与对策
| 误区 | 后果 | 对策 |
|---|---|---|
| 凭直觉优化 | 改了不痛的地方 | profiler 采样后再动手 |
| 以性能拒绝重构 | 热点之外持续劣化 | 只对热点保留例外 |
| 只测一次基准 | 噪声被当成结论 | 多次运行取中位数 |
| 忽略数据规模 | 小样本结论不成立 | 按生产量级设参数 |
把「重构导致变慢」的猜测变成一个可验证的假设:跑一遍基准就能确定,多数情况下差异在噪声范围内,而清晰的结构会让后续优化更容易做对。
为热点保留低可读的写法是合理的,但要留下证据:注释里写清度量数据、被测量规模与重新评估的条件,否则半年后没人敢动这段代码。