何时性能提升足够显著以实施该优化?

8
按照参考书的做法,在优化代码时我总是会衡量性能。然而,有时候性能提升并不明显,我无法决定是否实施此优化。例如,当一个修复在某些条件下将平均响应时间从100毫秒缩短到90毫秒时,我应该实施这个修复吗?如果将200ms缩短到190ms呢?在我能够得出整体上有益的结论之前,我应该尝试多少种情况呢?我想这并没有一个直截了当的答案,因为它取决于太多的因素,但是否有一些好的经验准则我应该遵循?是否有任何指南或最佳实践可以参考?
编辑:感谢大家的回答!我想这个故事的道理是,没有简单的方法告诉你是否应该这样做,但是有一些指导方针可以帮助这个过程。需要考虑的事情,不应该做的事情等等。这次我最终实施了这个修复,即使它将几行代码变成了20-30行代码。因为我们的应用程序非常注重性能,在各种实际情况下都能获得10%的稳定增长。

“按照教科书的要求” 那是哪本教科书?我真的很想知道这个想法是如何传播的。 - Mike Dunlavey
这是《Java并发编程实战》。我最喜欢的Java书籍 :) - Enno Shioji
10个回答

7
我认为(至少对我而言)准则有两个方面:
1. “它是否重要” - 在商业世界中,这通常意味着如果客户关心,那么它就很重要。也就是说,如果最终用户能够“注意到”100毫秒和90毫秒之间的差异(我在这里并不是在开玩笑),那么它是重要的。
2. 如果“它很重要”,那么你需要针对可能出现或至少可能出现的实际使用情况充分测试你的代码。如果一种优化在50%的情况下加速了代码,但另外50%的时间比以前慢,那么显然可能不值得实施。
关于上面的第一个观点:通过建议软件的最终用户可能会“注意到”10毫秒的差异,我并不是指他们实际上能够看到差异。但是,如果您的应用程序在连接数百万的服务器上运行,并且每个小的速度增加都可以从服务器上卸载大量负载,那么这对于运行服务器的客户端可能很重要。或者,如果您的应用程序执行极其时间关键的工作,则这是另一种情况,即使速度提高本身并不明显,10毫秒的加速结果可能是显著的。

7
你的问题唯一明智的方法是类似于“当受益大到足以值得你投入时间去探索、实施和测试优化时”的做法。
“受益大到足以值得”是极其主观的。如果你或你的雇主进行这个更改,能否销售更多的软件单位?你的用户群是否会注意到?拥有最快速的代码是否会让你感到满意?哪些或类似的问题适用是只有你自己才知道的。
总体而言,在我职业生涯的20多年里,我编写的大部分软件都已经“足够快”,而我关心的需要优化的代码则呈现为显而易见的瓶颈:查询时间过长、滚动过慢等等。

6

Donald Knuth在优化方面提出了以下两个观点:

"我们应该忘记小的效率问题,大约有97%的时间:过早的优化是万恶之源" [2]

"在已经建立的工程学科中,一个12%的改进很容易得到,从不被视为边缘,我认为这种观点也应适用于软件工程" [5]

来源: http://en.wikipedia.org/wiki/Program_optimization


那么这意味着什么?特别是当它们放在一起时? - ziggystar

3
  • 优化是否过度混淆了您的代码?
  • 您真的需要进行优化吗?如果您的应用程序运行良好,则代码的可读性可能更为重要。
  • 在尝试小型hacky优化之前,您是否先处理了应用程序的总体设计和算法?

3

您应该将优化工作集中在代码运行时间最长的部分。如果某段代码占总运行时间的80%,那么将其优化以减少5%的时间所产生的影响与将其余代码时间减少20%相同。

通常,优化会使代码更难读(并不总是如此,但通常是这样)。因此,在确定存在问题之前,请避免进行优化。


2
如果它确实能加速您的程序,为什么不实现呢?您已经通过创建新的实现完成了工作,因此应用新实现并不会增加额外的工作量。除非代码真的难以理解。另外,从100毫秒到90毫秒是性能提升了10%,这个数字不容忽视。真正的问题是,如果它一开始只需要100毫秒运行,那么优化它的意义何在?

@Kevin - 总体来说,你的回答很好,但是你最后的问题有一个显而易见的答案。如果服务器需要进行100万次这样的计算,10毫秒的差异意味着10,000秒和9,000秒之间的差异。相当显著。除非我在某个地方放错了一个重要数字 :) - DVK
@DVK 是的,但OP提到这只是一个微不足道的收益。我只是想指出优化可能在其他地方更合适。 - Kevin Crowell
Kevin - 是的,我完全同意更有影响力的优化比较少的优化更好。我只是指出,除非你知道小的绝对节省不会乘以一个非常大的因素,否则不应该基于小的绝对节省而忽视10%。 - DVK

2
只要足够快,就不需要再进行优化。但如果是这种情况,你甚至都不会费心去进行性能分析...

2
如果性能提升不大,则需要考虑其他因素:可维护性、更改风险、可理解性等。如果会降低代码的可维护性或可理解性,则可能不值得进行更改。如果可以提高这些属性,则更有理由实施更改。

1
在大多数情况下,你的时间比计算机更有价值。如果你认为稍后弄清楚代码正在做什么需要多花半个小时(例如如果有错误),而它只为你节省了几秒钟,那么你就处于净亏损状态。

1

这非常取决于使用场景。我在这里假设所讨论的代码已经进行了性能分析,因此已知它是瓶颈--即不仅仅是“这可能更快”,而是“如果这更快,程序将会更快地给出结果/完成运行”。在这种情况下不适用的情况下--例如,如果您花费99%的时间等待更多数据通过以太网连接传输--那么您应该关注正确性而不是优化速度。

  • 如果你正在编写用户界面代码,那么你关心的是感知速度。通常情况下,小于100毫秒的任何操作都被认为是“瞬间完成”--没有必要再加速了。
  • 如果你正在为一个巨大的服务器群编写代码,那么如果你的薪水成本比服务器额外用电成本低,那么这是值得的。(但一定要优先考虑你的时间。)
  • 如果你正在编写很少使用或无人看管时才会运行的代码,只要它在合理的时间内完成,就不用担心它。安装脚本通常属于这种类型(除非你开始遇到许多分钟的情况,此时用户可能会因为安装时间太长而放弃安装)。
  • 如果你正在编写自动化任务的代码,为别人节省时间,那么如果(你花费的编码时间+他们使用优化代码的时间)小于(他们使用缓慢代码的时间),那么这是值得的。如果你在商业环境中进行这项工作,请根据你们各自的薪水来权衡。
  • 如果你正在编写将被数千人使用的库代码,如果有时间,总是使其更快。
  • 如果你在时间压力下只需要让某些东西工作,例如作为演示,那么不要进行优化(除非通过从库中选择合理的算法来进行优化),除非结果太慢以至于它甚至不能“工作”。
个人认为最大的烦恼之一是找到软件,它可能最初属于一个类别,然后又转移到另一个类别,但没有人回去做必要的优化。直到最近,JavaScript 的性能就是一个很好的例子。故事的寓意是:不要只做一次决定;随着情况的变化重新审视问题。

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