今天是“技能进阶”单元的最后一节课,我也要兑现刚开始在“概论”里的承诺,讲一讲在运行阶段我们能做什么。
运行阶段能做什么
在编码阶段,你会运用之前学习的各种范式和技巧,写出优雅、高效的代码,然后把它交给编译器。经过预处理和编译这两个阶段,源码转换成了二进制的可执行程序,就能够在 CPU 上“跑”起来。
在运行阶段,C++ 静态程序变成了动态进程,是一个实时、复杂的状态机,由 CPU 全程掌控。但因为 CPU 的速度实在太快,程序的状态又实在太多,所以前几个阶段的思路、方法在这个时候都用不上。
所以,我认为,在运行阶段能做、应该做的事情主要有三件:调试(Debug)、测试(Test)和性能分析(Performance Profiling)。
调试你一定很熟悉了,常用的工具是 GDB,我在前面的“轻松话题”里也讲过一点它的使用技巧。它的关键是让高速的 CPU 慢下来,把它降速到和人类大脑一样的程度,于是,我们就可以跟得上 CPU 的节奏,理清楚程序的动态流程。
测试的目标是检验程序的功能和性能,保证软件的质量,它与调试是相辅相成的关系。测试发现 Bug,调试去解决 Bug,再返回给测试验证。好的测试对于软件的成功至关重要,有很多现成的测试理论、应用、系统(你可以参考下,我就不多说了)。
一般来说,程序经过调试和测试这两个步骤,就可以上线运行了,进入第三个、也是最难的性能分析阶段。
什么是性能分析呢?
你可以把它跟 Code Review 对比一下。Code Review 是一种静态的程序分析方法,在编码阶段通过观察源码来优化程序、找出隐藏的 Bug。而性能分析是一种动态的程序分析方法,在运行阶段采集程序的各种信息,再整合、研究,找出软件运行的“瓶颈”,为进一步优化性能提供依据,指明方向。
从这个粗略的定义里,你可以看到,性能分析的关键就是“测量”,用数据说话。没有实际数据的支撑,优化根本无从谈起,即使做了,也只能是漫无目的的“不成熟优化”,即使成功了,也只是“瞎猫碰上死耗子”而已。
性能分析的范围非常广,可以从 CPU 利用率、内存占用率、网络吞吐量、系统延迟等许多维度来评估。
今天,我只讲多数时候最看重的 CPU 性能分析。因为 CPU 利用率通常是评价程序运行的好坏最直观、最容易获取的指标,优化它是提升系统性能最快速的手段。而其他的几个维度也大多与 CPU 分析相关,可以达到“以点带面”的效果。
系统级工具
刚才也说了,性能分析的关键是测量,而测量就需要使用工具,那么,你该选什么、又该怎么用工具呢?
其实,Linux 系统自己就内置了很多用于性能分析的工具,比如 top、sar、vmstat、netstat,等等。但是,Linux 的性能分析工具太多、太杂,有点“乱花渐欲迷人眼”的感觉,想要学会并用在实际项目里,不狠下一番功夫是不行的。
所以,为了让你能够快速入门性能分析,我根据我这些年的经验,挑选了四个“高性价比”的工具:top、pstack、strace 和 perf。