nic*_*ckf 79 optimization premature-optimization
正如Knuth所说,
我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源.
这是Stack Overflow常常出现的问题,例如"哪个是最有效的循环机制","SQL优化技术?"等问题.(等等).这些优化提示问题的标准答案是分析您的代码并首先查看它是否是一个问题,如果不是,那么您的新技术就不再需要了.
我的问题是,如果某种技术不同但不是特别模糊或混淆,那真的可以被认为是过早的优化吗?
这是Randall Hyde的一篇名为"过早优化的谬误"的相关文章.
Nor*_*sey 101
Don Knuth开始了文学编程运动,因为他相信计算机代码最重要的功能是将程序员的意图传达给人类读者.任何使代码难以理解的编码实践都是过早的优化.
以优化的名义引入的某些习语已经变得如此受欢迎,以至于每个人都理解它们并且它们已经成为预期,而不是为时过早.例子包括
在C中使用指针运算而不是数组表示法,包括使用这样的习语
for (p = q; p < lim; p++)
Run Code Online (Sandbox Code Playgroud)将全局变量重新绑定到 Lua中的局部变量,如
local table, io, string, math
= table, io, string, math
Run Code Online (Sandbox Code Playgroud)除了这些成语之外,走捷径也是危险的.
除非,所有优化都是不成熟的
程序太慢(许多人忘记了这一部分).
您有一个测量(配置文件或类似),表明优化可以改善一些事情.
(也可以优化内存.)
直接回答问题:
编辑:在回应评论时,使用quicksort而不是像插入排序这样的简单算法是每个人都理解和期望的成语的另一个例子.(虽然如果你写了自己的排序例程,而不是使用库排序例程中,人们希望你有一个非常好的理由.)
Sma*_*acL 40
恕我直言,90%的优化应该在设计阶段进行,基于所需的电流,更重要的是,未来的要求.如果你必须拿出一个分析器,因为你的应用程序没有扩展到所需的负载你就已经太迟了,IMO将浪费大量的时间和精力而无法解决问题.
通常,唯一值得的优化是那些能够在速度或存储或带宽乘数方面提高数量级性能的优化.这些类型的优化通常与算法选择和存储策略有关,并且极难逆转到现有代码中.它们可能会影响您对实现系统的语言的决策.
所以我的建议是,根据您的要求提前进行优化,而不是根据您的代码进行优化,并考虑应用程序的可能延长寿命.
Jar*_*Par 30
如果您还没有进行过分析,那就太早了.
Sho*_*og9 27
我的问题是,如果某种技术不同但不是特别模糊或混淆,那真的可以被认为是过早的优化吗?
嗯......所以你手头有两种技术,成本相同(使用,阅读,修改同样的努力),一种更有效.不,在这种情况下,使用效率更高的人不会为时过早.
中断你的代码编写,寻找常见的编程结构/库例程的替代方案,尽管有一个更有效的版本挂在某处,即使你知道所写的相对速度永远不会真正重要. .. 那是不成熟的.
首先,让代码工作.其次,验证代码是否正确.第三,快点.
在阶段#3之前完成的任何代码更改肯定为时过早.我不完全确定如何对之前做出的设计选择进行分类(比如使用非常适合的数据结构),但我更愿意转向使用抽象方法,而不是那些表现良好的人,直到我在我可以开始使用分析并具有正确(但通常很慢)的参考实现来比较结果的阶段.
你似乎在谈论的是优化,比如使用基于散列的查找容器与像数组一样的索引容器,当进行大量的键查找时.这不是过早的优化,而是您应该在设计阶段决定的事情.
Knuth规则的优化类型是最小化最常见代码路径的长度,优化最常运行的代码,例如在汇编中重写或简化代码,使其不那么通用.但是,在确定代码的哪些部分需要这种优化并且优化意愿(可能?)使代码更难理解或维护之前,这样做是没有用的,因此"过早优化是所有邪恶的根源".
Knuth还说,改变程序使用的算法,而不是优化,总是更好,这是解决问题的方法.例如,稍微调整可能会使优化速度提高10%,从根本上改变程序的工作方式可能会使速度提高10倍.
针对这个问题上发表的很多其他评论做出反应:算法选择!=优化
从数据库的角度来看,在设计阶段不考虑优化设计充其量是蛮干的.数据库不容易重构.一旦它们的设计很糟糕(这就是一个不考虑优化的设计,无论你怎么试图隐藏在过早优化的废话之后),几乎永远无法从那恢复,因为数据库太基础了整个系统的运作.考虑到您期望的情况的最佳代码,而不是等到有一百万用户并且人们尖叫,因为您在整个应用程序中使用游标,正确设计成本要低得多.其他优化,例如使用可搜索代码,选择看起来最好的索引等等,只有在设计时才有意义.有一个原因可以称之为快速和肮脏.因为它不能很好地工作,所以不要使用快速作为良好代码的替代品.坦率地说,当您了解数据库中的性能调优时,您可以编写更有可能在同一时间内执行良好的代码,或者编写代码执行效果不佳的代码.没花时间去学习什么是性能良好的数据库设计是开发人员的懒惰,而不是最佳实践.
格言的要点是,通常,优化是复杂的和复杂的.而通常,你建筑师/设计师/程序员/维护者需要清晰,简洁的代码,以便了解正在发生的事情.
如果特定的优化是清晰简洁的,请随意尝试(但请返回并检查优化是否有效).重点是在整个开发过程中保持代码清晰简洁,直到性能的好处超过编写和维护优化的诱导成本.
优化可以在不同的粒度级别上进行,从非常高的级别到非常低的级别:
从良好的架构、松散耦合、模块化等开始。
为问题选择正确的数据结构和算法。
优化内存,尝试在缓存中容纳更多代码/数据。内存子系统比 CPU 慢 10 到 100 倍,如果将数据分页到磁盘,则速度会慢 1000 到 10,000 倍。对内存消耗保持谨慎比优化单个指令更有可能带来重大收益。
在每个函数中,适当使用流程控制语句。(将不可变表达式移到循环体之外。将最常见的值放在 switch/case 等中)
在每个语句中,使用最有效的表达式来产生正确的结果。(乘法与移位等)
对是否使用除法表达式或移位表达式进行挑剔并不一定是过早的优化。如果您没有首先优化架构、数据结构、算法、内存占用和流控制,那么这样做还为时过早。
当然,如果您没有定义目标性能阈值,任何优化都是不成熟的。
在大多数情况下,要么:
A) 您可以通过执行高级优化来达到目标性能阈值,因此无需摆弄表达式。
或者
B) 即使在执行所有可能的优化之后,您也不会达到目标性能阈值,并且低级优化不会在性能上产生足够的差异来证明可读性损失是合理的。
根据我的经验,大多数优化问题都可以在架构/设计或数据结构/算法级别解决。通常(尽管并非总是)需要优化内存占用。但很少需要优化流程控制和表达式逻辑。在那些确实有必要的情况下,这很少是足够的。