最危险的性能瓶颈误解

9
最近编写基于云的画布式代码编辑器Bespin的开发人员谈到了他们如何重构和优化Bespin代码的部分,因为他们误认为JavaScript很慢。事实证明,当一切都说完了,他们的优化并没有产生显著的改进。
我相信我们中的许多人会费尽心思地编写“优化”的代码,基于类似Bespin团队的误解。
开发人员通常存在哪些常见性能瓶颈误解?
8个回答

18

按照无特定顺序:

"准备好,开火,再瞄准" - 认为你知道需要优化的内容而没有证明它(即猜测),并基于此行动,由于没有帮助很多,因此假设代码一开始就是最优的。

"斤钱省下,两磅亏本" - 认为优化完全是关于编译器优化,却在过度设计,尤其是数据结构和数据库方面花费大量时间。

"用重型武器打苍蝇" - 对在课堂上听到的最花哨的想法如此着迷,以至于不管规模大小都可以使用它们。

"对性能的模糊思维" - 滥用像"hotspot"、"bottleneck"、"profiler"、"measure"这样的术语,似乎这些东西被充分理解和 / 或相关。(我敢打赌我会因为这个受到打击!)好的,一个一个来:

  • hotspot - 它的定义是什么?我有一个:它是物理地址的一个区域,在这个区域中寄存器PC被找到了相当大的一部分时间。这是PC采样器擅长找到的东西。许多性能问题表现为hotspots,但只有在最简单的程序中问题才与hotspot在同一位置

  • 瓶颈 - 这是一个用于描述性能问题的通用术语,它意味着一个限制任务完成速度的有限通道。未明确说明的假设是这些任务是必要的。在我几十年的性能调整经验中,我实际上发现了很少一部分问题是这样的。几乎所有的都是不同的性质。与其说是从A点到B点走最短路,不如说是采取小的绕路,以函数调用的形式进行,虽然代码量很少,但花费的时间却不少。然后这些绕路进一步嵌套,有时甚至达到30级的深度。嵌套越多,就越有可能存在一些不必要的-事实上是浪费的-绕路,几乎总是源自泛化失控——在“抽象化”方面过度放纵而不加思考。

  • 分析器 - 一个万能好东西,对吧?你只需要获得一个分析器并进行一些分析,没错吧?你曾经想过当你的目标是找出需要修复以获得更好性能的问题时,有多容易让分析器误导你告诉你很多无用信息吗?在你的调用树中,加入一点文件I/O,或者一点系统例程的调用,或让你的邪恶双胞胎在你不知道的情况下做这件事。在某个时候,这将成为你的问题,而大多数分析器将完全忽略它,因为他们所考虑的唯一低效率是算法效率。或者,你的所有程序可能不会都是小程序,并且它们可能不会在少量地方调用另一个程序,因此你的调用图表显示两个程序之间存在链接,但是哪个调用呢?或者假设你可以计算出某个路径A调用B调用C的时间占用了大部分的时间。你可以看看那个并认为你不能做太多事情来解决它,但如果你也可以查看在这些调用中传递的数据,你就可以看到它是否必要。这是一个有趣的项目-选择你最喜欢的分析器,看看你可以用多少种方法愚弄它。也就是说,找到让程序变慢的方法,而不让分析器能够判断你做了什么,因为如果你能故意这样做,那么你也可以无意中这样做。

  • 测量 - (即测量时间)这是分析器已经做了几十年的事情,他们以精确和准确地测量而自豪。但是测量什么时间呢?为什么要精确?请记住,目标是精确定位性能问题,以便您可以有成效地优化它们以获得加速。当您获得该加速时,它就是它,无论您事先估计得多么精确。如果在精度测量的代价下换取定位的精度,那么您刚刚买了苹果,而您需要的是橘子。

  • 这里有一些关于性能的误解的清单。


    2
    嗯,性能分析工具对我非常有用,而且我通过它们进行了可衡量和可感知的改进... 我不太明白你的意思。 - alex
    2
    @alex:是的,他们发现了一些问题。你知道你没有更多的加速机会吗?缺乏证据并不意味着不存在证据。这是我的一个例子,在几次迭代中,展示了超过40倍的加速:https://dev59.com/mnNA5IYBdhLWcg3whuV_#927773 - Mike Dunlavey
    1
    +1,尽管我不同意(或者误解)“瓶颈”这个词。我的看法是:瓶颈描述了限制硬件组件的部分 - 例如CPU、缓存、磁盘。当运行计算密集型程序时,很少所有组件都处于极限状态 - 通常只有一个会成为瓶颈。您可以减少总体负载,可以从一个组件中去除“压力”,使其不会那么早地成为瓶颈,并且可以在组件之间移动“压力”。 - peterchen
    @peterchen:你说得对。我的问题是,这个术语通常被应用于任何使软件运行时间超过预期的情况,而作为一个比喻,它是具有误导性的。它暗示着赛马受到腿部移动速度的限制(例如)。当然,但在非玩具软件中,压倒性的典型问题是,赛马不是直线奔跑,而是遵循嵌套绕路的分形海岸线,其中许多并不真正必要。我希望有一个更好的隐喻来捕捉这个想法,因为人们并不真正意识到它。 - Mike Dunlavey
    @peterchen:也许另一种说法是,我们的调用树可能会变得过于庞大,需要修剪。有没有一个词可以形容这种情况?也许可以叫做“葛藤代码”? - Mike Dunlavey
    感谢您的反馈-我同意。编译器和特别是硬件在处理Kudzu(不得不查一下!)方面取得了惊人的进展。然而,增长似乎总是比收益高出一点点。仍然有更多需要修剪的地方。 - peterchen

    14

    如果没有有效的配置文件,进行优化时会发生什么?你所做的一切都只是猜测,很可能会浪费时间和金钱。我可以列出一堆其他的误解,但许多问题其实就是:如果问题代码不是占用最多资源的部分,那它可能已经足够好了。就像是展开正在执行磁盘I/O的for循环一样...


    4
    最大的误解就是——你认为自己知道为什么速度慢。进行性能分析!进行性能分析!进行性能分析! - Jason Peacock
    4
    关键词是“有效”。确保用于识别瓶颈的性能测试类似于生产负载。 - Binil Thomas

    6
    • 关系型数据库很慢。
    • 我比优化器更聪明。
    • 这应该被优化。
    • Java很慢。

    而且,与此无关:

    有些人遇到问题时,会想:“我知道了,我会使用正则表达式。”现在他们有两个问题了。

    -jwz


    哎呀,当我写我的答案时这个回答还没有出现!哈哈。 :DDD - slacker
    最有趣的是,我们两个的回答都得到了同样多的点赞:D。 - slacker

    6

    如果我将整个代码库转换为[在此插入xxx最新技术],它会更快。


    那个误解更多地是由PHBs拥有,而不是程序员本身。猜猜是谁做出决定... - slacker

    5
    • 优化代码中的错误部分(各位,请使用性能分析器!)。
    • 我的编译器中的优化器很聪明,所以我不需要帮它。
    • Java很快(哈哈哈)
    • 关系型数据库很快(大笑,哈哈哈,LMAO)

    你能为我们解释一下 ROTFLLOLLMAO 吗? - David Murdoch
    叹气。我知道 ROTFLMAO。中间的“LLOL”部分是什么?还是“LOLL”? :-) - David Murdoch
    R.olling O.n T.he F.loor L.aughing L.aughing O.ut L.oud L.aughing M.y A.ss O.ff. 我认为 ROTFLMAO 更有意义。 :-) - David Murdoch

    5

    "这一定要尽可能快。"

    如果您没有性能问题,您就不需要担心优化性能(除了注意使用良好的算法之外)。

    这种误解还表现在尝试优化程序每个方面的性能上。我经常看到人们试图削减低容量网络应用程序执行时间的每一毫秒,而未考虑到网络延迟将比他们代码的执行时间长得多,使得任何执行时间的缩短都无关紧要。


    3

    我的优化规则:

    • 不要优化。
    • 现在不要优化。
    • 使用分析工具来识别问题。
    • 优化占用至少80%时间的组件。
    • 找到一个比原来快10倍的优化方法。

    我最好的优化经验是将一个报表从3天缩短到9分钟。优化后的代码速度从3天加快到了3分钟。

    在我的职业生涯中,我遇到过三个人被要求在VAX上生产比本地排序更快的排序算法。但他们最终只能生产出比原来慢三倍的排序算法。


    2

    这些规则很简单:

    1. 首先尝试使用标准库函数。
    2. 其次采用暴力和无知的方式。
    3. 在尝试优化之前,证明你确实存在问题。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接