我是否正确理解过早优化?

我一直在努力处理我正在编写的一个应用程序,我想我已经开始看到我的问题是不成熟的优化。 我的完美主义者想让所有事情都是最优化的,并且第一次完美无缺,但我发现这使得设计变得相当复杂。 为了更好地实现一件简单的事情,我没有写出小巧的,可测试的函数,而是倾向于尽可能多地填充功能。

例如,我避免了多次到数据库访问同一条信息,代价是代码变得更加复杂。 我的一部分想要不必担心冗余数据库调用。 这将使编写正确的代码变得更加容易,并且无论如何,所提取的数据量都很小。 我的另一部分感觉非常肮脏,不干净。 :-)

我倾向于多次访问数据库,我认为这是正确的举措。 我完成这个项目更加重要,因为这样的优化,我觉得我会挂断电话。 我的问题是: 这是避免过早优化的正确策略吗?


总的来说,这是正确的策略。 让代码工作,彻底覆盖自动化测试。

然后,您可以在程序处于分析器控制下运行自动化测试,以找出程序花费时间和/或内存的位置。 这将告诉你在哪里进行优化。

它将向您展示如何优化工作代码,而不是将所有代码放在一起的代码。

你不希望代码失败。


我不记得的报价是来自Mich Ravera:

如果它不起作用,它无法工作的速度无关紧要。


我们应该忘记小效率,大约97%的时间:过早优化是所有邪恶的根源。 - 霍尔

虽然@约翰桑德斯认为它,但单独应用TDD可能无法完全解决您的担忧。 我坚持使用TDD,当你正确地进行TDD时,如果你可以有效地应用重构,你通常会得到更精简的代码,并且你知道它的好处。 那里没有争论。

但是,我看到太多的开发人员编写性能不明的代码 - 避免过早优化不适合编写草率/懒惰/朴素代码。 编写单元测试并不妨碍这一点。 尽管编写单元测试的人可能是一个更好的编码器,并且更好的编码人员不会像往常一样编写错误的代码。

编写测试,并将性能测试纳入您的利益相关方识别的场景的测试套件中。 例如为特定供应商检索100个打折产品,并在3秒内将库存水平和格式包含为Xml

“过早优化”与“关注性能”相同的错误不应该引导软件开发。 - 兰德尔海德

如果您太迟离开性能问题,您可能会发现改变太难或太昂贵。

一些文章

  • 过早优化的谬误
  • 过早优化

  • Knuth对我的引用的关键方面是“便士和笨蛋”。 这就是他最终描述过早的优化者的原因 - 有人在有英镑可以挽救的时候节省便士,并努力维持他们的“优化”(注意他在这里如何使用引号)软件。

    我发现很多人经常只引用Knuth的一小部分论文。 值得一提的是,他的论文正在争论使用goto来加速软件中的关键执行路径。

    更完整的报价:

    如果n的平均值大约为20,并且在程序中执行了大约一百万次的搜索例程,则整体运行速度明显节省。 这种循环优化[使用gotos]并不难学,正如我所说,它只适用于程序的一小部分,但它们通常可以节省大量成本。 [...]

    许多当今软件工程师所共有的传统观点认为,忽视小型计算机的效率, 但我认为这只是对他们认为正在被愚蠢而愚蠢的程序员实施的滥用行为的过度反应,他们无法调试或维护他们的“优化”程序。 在已建立的工程学科中,容易获得的12%的改进永远不会被认为是边际的; 我相信软件工程应该以同样的观点为准。 当然,我不打算在单项工作上做出这样的优化,但是当它是一个准备高质量程序的问题时,我不想限制自己使用那些否认这种效率的工具。

    毫无疑问,效率的瓶颈会导致滥用。 程序员浪费大量的时间来思考或者担心程序中非关键部分的速度,而这些效率的尝试实际上在考虑调试和维护时会产生强烈的负面影响。 我们应该忘记小效率,比如97%的时间; 过早优化是万恶之源。

    对程序的哪些部分是非常关键的先决判断往往是错误的,因为一直在使用测量工具的程序员的普遍经验是,他们的直觉猜测失败了。 在使用这些工具七年之后,我确信从现在开始编写的所有编译器都应该被设计为向所有程序员提供反馈,说明他们程序的哪些部分花费最大; 事实上,这个反馈应该自动提供,除非它已被明确关闭。

    在程序员知道他的例程的哪些部分非常重要之后,像加倍循环这样的转换将是值得的。 请注意,这个转换引入go to语句 - 所以还有几个其他的循环优化。

    所以这是来自一个真正关心微观层面表现的人,并且当时(优化者现在已经好多了),正在利用goto来提高速度。

    Knuth建立“不成熟优化者”的核心是:

  • 基于没有过去经验或测量的直觉/迷信/人类直觉进行优化(盲目优化而不知道自己在做什么)。
  • 优化的方式可以节省超过磅的便士(无效优化)。
  • 寻求一切绝对的效率最终高峰。
  • 在非关键路径中寻求效率。
  • 在几乎不能维护/调试代码时尝试优化。
  • 这些与您的优化时间无关,而是与经验和理解有关 - 从理解关键路径到了解实际提供的性能。

    Knuth的论文没有涉及测试驱动开发和界面设计等主要方面。 这些是更现代的概念和想法。 他主要关注实施。

    尽管如此,这是对Knuth建议的一个很好的更新 - 试图通过测试来确立正确性,以及界面设计,这些设计让您有空间进行优化而不会破坏一切。

    如果我们尝试应用Knuth的现代解释,我会在那里添加“船”。 即使你正在以测量的增益优化软件的真正关键路径,世界上最快的软件如果从未出货也毫无价值。 牢记这一点应该可以帮助你做出更明智的妥协。

    我倾向于多次访问数据库,我认为这是正确的举措。 我完成这个项目更加重要,因为这样的优化,我觉得我会挂断电话。 我的问题是:这是避免过早优化的正确策略吗?

    在你最密切地理解你自己的要求的时候,考虑到以上的一些观点,你会发展出最好的判断。

    我建议的一个关键因素是,如果这是一个处理重负载的性能关键路径,那么以一种留有足够空间进行优化的方式来设计公共接口。

    例如,不要设计具有客户端依赖于Particle接口的Particle系统。 当你只有封装状态和单个粒子的实现工作时,没有余地进行优化。 在这种情况下,您可能必须对代码库进行级联更改才能进行优化。 如果道路只有10米长,赛车不能利用它的速度。 相反,设计朝向ParticleSystem界面聚集了一百万个粒子,例如,在可能的情况下用较高级别的操作来处理粒子。 如果您发现需要进行优化,那么您就有足够的空间进行优化而不会破坏设计。

    我的完美主义者想让所有事情都是最优化的,并且第一次完美无缺,但我发现这使得设计变得相当复杂。

    现在这部分听起来有点不成熟。 一般来说,你的第一关应该是简单。 即使你正在做一些冗余的工作,简单性也往往比你想象的更快,更快。

    无论如何,我希望这些观点有助于至少增加更多的考虑因素。

    链接地址: http://www.djcxy.com/p/39631.html

    上一篇: Am I understanding premature optimization correctly?

    下一篇: Is it feasible to virtualize developer machines?