优化思想
1. 必须测量性能
人的感觉对于检测性能提高了多少来说是不够精确的。人的记忆力不足以准确地回忆起以
往多次实验的结果。本内侧的知识可能会误导你,使你相信了一些并非总是正确的事情。
当判断是否应当对某段代码进行优化的时候,开发人员的直觉往往差得令人吃惊。他们
编写了函数,也知道这个函数会被调用,但他们并不清楚调用频率以及会被什么代码所调
用。于是,一段低效的代码混入了核心组件中并被调用了无数次。经验也可能会欺骗你。
编程语言、编译器、库和处理器都在不断地发展。之前曾经肯定是热点的函数可能会变得
非常高效,反之亦然。只有测量才能告诉你到底是在优化游戏中取胜了还是失败了。
那些具有最让我折服的优化技巧的开发人员都会系统地完成他们的优化任务:
• 他们做出的预测都是可测试的,而且他们会记录下预测;
• 他们保留代码变更记录;
• 他们使用可以使用的最优秀的工具进行测量;
• 他们会保留实验结果的详细笔记。
2.优化器是王牌猎人
优化器是王牌猎人。如果只能让程序的运行速度提高 1% 是不值得冒险去修改代码的,因为修改代码可能会引入 bug。只有能显著地提升性能时才值得修改代码。而且,这 1% 的
速度提升可能只是将测量套件的误差当作了性能改善。因此,我们必须用随机抽样统计
和置信水平来证明速度的提升。但是完全没有必要为了这么一点点性能提升花费这么大气
力。本内容中不会推荐大家这么做。
当性能提升 20% 的时候,事情就完全不同了。它会消除所有反对方法论的声音。本内容中虽
然没有太多统计数字,不过我并不会为此感到抱歉。本内容的重点是帮助开发人员找到这样
的性能改善点:其显著的效果足以战胜任何对其价值的质疑。这些性能改善点可能仍然取
决于操作系统和编译器等因素,因此它们可能会在其他操作系统上或是其他时间点没有太
好的效果。但是即使开发人员把他们的代码移植到新操作系统上,这些修改也几乎从来都
不会反过来降低程序性能。
3. 90/10规则
性能优化的基本规则是 90/10 规则:一个程序花费 90% 的时间执行其中 10% 的代码。这
只是一条启发性的规则,并非自然法则,但对于我们的思考和计划却具有指导性。这条规
则有时也被称为 80/20 规则,但思想是一样的。直观地说,90/10 规则表示某些代码块是会
被频繁地执行的热点(hot spot),而其他代码则几乎不会被执行。这些热点就是我们要进
行性能优化的对象。
90/10 规则的一个结论是,优化程序中的所有例程并没有太大帮助。优化一小部分代码事
实上已经足够提供你所想要的性能提升了。识别出 10% 的热点代码是值得花费时间的,但
靠猜想选择优化哪些代码可能只是浪费时间。
正如有些人所建议的那样,高德纳博士也并非警告我们所有的优化都是罪恶的。他只是说
浪费时间去优化那非关键的 90% 的程序是罪恶的。很明显,他也意识到了 90/10 规则。
4 . 阿姆达尔定律
阿姆达尔定律是由计算机工程先锋基恩 • 阿姆达尔(Gene Amdahl)提出并用他的名字命名
的,它定义了优化一部分代码对整体性能有多大改善。阿姆达尔定律有多种表达方式,不
过就优化而言,可以表示为下面的等式:
(1 )
S(t)= 1/(1-P)+P/S(p)
其中 S(t) 是因优化而导致程序整体性能提升的比率,P 是被优化部分的运行时间占原来程序
整体运行时间的比例,S(p) 是被优化部分 P 的性能改善的比率。
例如,假设一个程序的运行时间是 100 秒。通过分析前面发现程序花费了 80
秒多次调用函数 f。现在假设修改 f 使其运行速度提升了 30%,那么这对程序整体运行时
间有多大改善呢?
24 | 第 3 章
P 是函数 f 的运行时间占原来程序整体运行时间的比例,即 0.8;SP 是被优化的部分 P 的
性能改善的比率,即 1.3。将它们代入到阿姆达尔定律的公式中:
(1 0.8) 1.3
0.8
1
0.2 0.62
1 1.22S T
- +
= + ==
也就是说,将这个函数的性能提升 30% 会将程序整体运行时间缩短 22%。在这个例子中,
阿姆达尔定律证明了 90/10 规则,而且通过这个例子向我们展示了,对 10% 的热点代码进
行适当的优化,就可以带来如此大的性能提升。
现有一个函数 g 的运行时间是 10 秒。现在假设你修改了函数 g,将它的运行速度提高了
100 倍。那么这对程序整体性能的提升有多大呢?
P 是函数 g 的运行时间占原来程序整体运行时间的比例,即 0.1;SP 是 100。将它们代入到
阿姆达尔定律的公式中:
1 00
1 9 001 11
(1 0. ) 1
0.
1
0. 0.
1 1.S T
-
=
+
= + =
在这个例子中阿姆达尔定律是具有警示性的。即使有异常优秀的编码能力或是黑科技将函
数 g 的运行时间缩短为 0,它仍然是那并不重要的 90% 代码中的一部分。将性能提升的比
率精确到两个小数位后,对程序整体性能的提升依然只有 11%。阿姆达尔定律告诉我们,
如果被优化的代码在程序整体运行时间中所占的比率不大,那么即使对它的优化非常成功
也是不值得的。阿姆达尔定律的教训是,当你的同事兴冲冲地在会议上说他知道如何将一
段计算处理的速度提高 10 倍,这并不一定意味着性能优化工作就此结束了。