我最具争议的编程观点是
发现性能问题与测量无关,而是与捕获有关。
如果你在一个房间里寻找大象(而不是老鼠),你需要知道它们有多大吗?不!你要做的就是看。
它们的巨大使得它们很容易被发现!
没有必要先测量它们。
至少从关于gprof的论文开始,度量的思想就已经成为常识
(Susan L. Graham, et al 1982)*,而一直以来,就在我们的眼皮底下,有一种非常简单直接的方法来寻找值得优化的代码。
作为一个小例子,下面是它的工作原理。假设您从调用堆栈中抽取5个随机时间样本,并且恰好在5个样本中的3个样本中看到特定的指令。这说明了什么?
............. ............. ............. ............. .............
............. ............. ............. ............. .............
Foo: call Bar ............. ............. Foo: call Bar .............
............. Foo: call Bar ............. ............. .............
............. ............. ............. Foo: call Bar .............
............. ............. ............. ............. .............
............. .............
它告诉你程序花费60%的时间做指令请求的工作。去掉它就去掉了60%:
...\...../... ...\...../... ............. ...\...../... .............
....\.../.... ....\.../.... ............. ....\.../.... .............
Foo: \a/l Bar .....\./..... ............. Foo: \a/l Bar .............
......X...... Foo: cXll Bar ............. ......X...... .............
...../.\..... ...../.\..... ............. Foo: /a\l Bar .............
..../...\.... ..../...\.... ............. ..../...\.... .............
/ \ .../.....\... / \ .............
约。
如果您可以删除指令(或更少地调用它),大约是2.5倍的加速。(注意-递归是无关紧要的-如果大象怀孕了,它不会更小。)
然后你可以重复这个过程,直到你真正接近最优。
这并不需要精确的测量、函数计时、调用计数、图表、数百个样本,以及任何典型的分析内容。
有些人在遇到性能问题时就使用这种方法,但他们不明白这有什么大不了的。
Most people have never heard of it, and when they do hear of it, think it is just an inferior mode of sampling. But it is very different, because it pinpoints problems by giving cost of call sites (as well as terminal instructions), as a percent of wall-clock time. Most profilers (not all), whether they use sampling or instrumentation, do not do that. Instead they give a variety of summary measurements that are, at best, clues to the possible location of problems. Here is a more extensive summary of the differences.
*事实上,这篇论文声称gprof的目的是“帮助用户评估抽象的替代实现”。它并没有声称可以帮助用户定位需要替代实现的代码,在比函数更精细的级别上。
我第二个最具争议的观点是这个,如果它不是那么难以理解的话。