性能分析
复习
- 日志与调试:先观察,再动手
- 大 O 记号:描述代价随规模的增长
- 循环优化:优化优先盯热点
TL;DR
- 优化之前先测量,别凭感觉
- 性能分析用来找出真正的瓶颈
- 瓶颈往往集中在少数热点上
- 先测再改,改后再测
正文
程序能跑,但可能有点慢。想让它更快,第一反应往往是“我觉得这里慢,改改看”。这恰恰是最容易走弯路的地方。
别凭感觉优化
有一条很有名的忠告:过早优化是万恶之源。 它想说的不是“不要优化”,而是不要凭直觉优化。
因为人对性能瓶颈的直觉,常常是错的。你以为最耗时的那个函数,实际可能根本没被调用几次;真正拖慢程序的,也许藏在一个你从没注意的角落。在没有数据的情况下优化,很可能是在做无用功,甚至把代码改得更复杂、更慢。
先测量,找瓶颈
正确的做法是先测量。性能分析(profiling)就是干这个的:它统计出程序把时间都花在了哪里——哪个函数调用最多、哪段代码最耗时。
有了分析结果,你会发现一个很普遍的现象:瓶颈往往高度集中——可能 80% 的时间,都花在 20% 的代码上。这就是所谓的“热点”。
这和前面讲算法、讲循环优化时的思路完全一致:把力气花在真正的热头上。 区别只在于,这里的“热点”是靠实测找出来的,而不是靠猜。
测—改—再测
找到热点之后,优化它,然后再测量一次:
- 确实变快了吗?
- 会不会把瓶颈转移到了别处?
- 有没有引入新的问题?
因为优化常常是“按下葫芦浮起瓢”:这里快了,别处成了新瓶颈。所以要循环往复:测量 → 优化 → 再测量,直到达到目标。
用数据说话,而不是用感觉。 这条原则,从调试一直贯穿到性能优化。
思考题 1
为什么优化前要先“测量”?
思考题 2
为什么性能瓶颈常常集中在少数热点上?
小结
知识点
- 不要凭直觉优化,应先测量
- 性能分析找出时间花在哪里
- 瓶颈常集中在少数热点代码
- 采用“测量—优化—再测量”的循环
参考资料
- Wikipedia(zh):性能分析:测量程序各部分的资源消耗
- Wikipedia(zh):性能工程:以测量为基础改进系统性能
思考题答案(仅供参考)
思考题 1
因为人对瓶颈的直觉常常不准,可能优化了根本不影响性能的地方,白费力气甚至弄糟代码。先测量才能知道时间真正花在哪里,让优化有的放矢。
思考题 2
因为程序各部分被执行的频率和耗时差异很大:少数代码会被大量重复执行(热点),占据了大部分时间,而多数代码很少运行。因此把优化集中在这些热头上,收益最高。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪