我相信我们中的许多人会费尽心思地编写“优化”的代码,基于类似Bespin团队的误解。
开发人员通常存在哪些常见性能瓶颈误解?
按照无特定顺序:
"准备好,开火,再瞄准" - 认为你知道需要优化的内容而没有证明它(即猜测),并基于此行动,由于没有帮助很多,因此假设代码一开始就是最优的。
"斤钱省下,两磅亏本" - 认为优化完全是关于编译器优化,却在过度设计,尤其是数据结构和数据库方面花费大量时间。
"用重型武器打苍蝇" - 对在课堂上听到的最花哨的想法如此着迷,以至于不管规模大小都可以使用它们。
"对性能的模糊思维" - 滥用像"hotspot"、"bottleneck"、"profiler"、"measure"这样的术语,似乎这些东西被充分理解和 / 或相关。(我敢打赌我会因为这个受到打击!)好的,一个一个来:
hotspot - 它的定义是什么?我有一个:它是物理地址的一个区域,在这个区域中寄存器PC被找到了相当大的一部分时间。这是PC采样器擅长找到的东西。许多性能问题表现为hotspots,但只有在最简单的程序中问题才与hotspot在同一位置。
瓶颈 - 这是一个用于描述性能问题的通用术语,它意味着一个限制任务完成速度的有限通道。未明确说明的假设是这些任务是必要的。在我几十年的性能调整经验中,我实际上发现了很少一部分问题是这样的。几乎所有的都是不同的性质。与其说是从A点到B点走最短路,不如说是采取小的绕路,以函数调用的形式进行,虽然代码量很少,但花费的时间却不少。然后这些绕路进一步嵌套,有时甚至达到30级的深度。嵌套越多,就越有可能存在一些不必要的-事实上是浪费的-绕路,几乎总是源自泛化失控——在“抽象化”方面过度放纵而不加思考。
分析器 - 一个万能好东西,对吧?你只需要获得一个分析器并进行一些分析,没错吧?你曾经想过当你的目标是找出需要修复以获得更好性能的问题时,有多容易让分析器误导你告诉你很多无用信息吗?在你的调用树中,加入一点文件I/O,或者一点系统例程的调用,或让你的邪恶双胞胎在你不知道的情况下做这件事。在某个时候,这将成为你的问题,而大多数分析器将完全忽略它,因为他们所考虑的唯一低效率是算法效率。或者,你的所有程序可能不会都是小程序,并且它们可能不会在少量地方调用另一个程序,因此你的调用图表显示两个程序之间存在链接,但是哪个调用呢?或者假设你可以计算出某个路径A调用B调用C的时间占用了大部分的时间。你可以看看那个并认为你不能做太多事情来解决它,但如果你也可以查看在这些调用中传递的数据,你就可以看到它是否必要。这是一个有趣的项目-选择你最喜欢的分析器,看看你可以用多少种方法愚弄它。也就是说,找到让程序变慢的方法,而不让分析器能够判断你做了什么,因为如果你能故意这样做,那么你也可以无意中这样做。
测量 - (即测量时间)这是分析器已经做了几十年的事情,他们以精确和准确地测量而自豪。但是测量什么时间呢?为什么要精确?请记住,目标是精确定位性能问题,以便您可以有成效地优化它们以获得加速。当您获得该加速时,它就是它,无论您事先估计得多么精确。如果在精度测量的代价下换取定位的精度,那么您刚刚买了苹果,而您需要的是橘子。
如果没有有效的配置文件,进行优化时会发生什么?你所做的一切都只是猜测,很可能会浪费时间和金钱。我可以列出一堆其他的误解,但许多问题其实就是:如果问题代码不是占用最多资源的部分,那它可能已经足够好了。就像是展开正在执行磁盘I/O的for循环一样...
而且,与此无关:
有些人遇到问题时,会想:“我知道了,我会使用正则表达式。”现在他们有两个问题了。
-jwz
如果我将整个代码库转换为[在此插入xxx最新技术],它会更快。
"这一定要尽可能快。"
如果您没有性能问题,您就不需要担心优化性能(除了注意使用良好的算法之外)。
这种误解还表现在尝试优化程序每个方面的性能上。我经常看到人们试图削减低容量网络应用程序执行时间的每一毫秒,而未考虑到网络延迟将比他们代码的执行时间长得多,使得任何执行时间的缩短都无关紧要。
我的优化规则:
我最好的优化经验是将一个报表从3天缩短到9分钟。优化后的代码速度从3天加快到了3分钟。
在我的职业生涯中,我遇到过三个人被要求在VAX上生产比本地排序更快的排序算法。但他们最终只能生产出比原来慢三倍的排序算法。
这些规则很简单: