什么时候优化过早?

时间:2011-01-28 20:16:59

标签: c# .net performance optimization premature-optimization

我看到这个术语使用了很多,但我觉得大多数人都是出于懒惰或无知而使用它。例如,我正在阅读这篇文章:

http://blogs.msdn.com/b/ricom/archive/2006/09/07/745085.aspx

他谈到他的决定时,他会为他的应用程序实现必要的类型。

如果是我,请谈谈我们需要编写的代码,其他程序员会想到:

  1. 当没有任何东西,从而过早地优化时,我正在思考太多。
  2. 在没有经历减速或性能问题时过度思考微不足道的细节。
  3. 或两者兼而有之。

    并且建议只是实施它,并且在它们成为问题之前不要担心它们。

    哪个更优惠?

    如何在任何实施完成之前区分性能关键应用程序的过早优化与知情决策?

10 个答案:

答案 0 :(得分:13)

如果出现以下情况,优化还为时过早:

  1. 您的应用程序没有做任何时间紧迫的事情。 (这意味着,如果你正在编写一个程序,在一个文件中添加500个数字,“优化”这个词甚至不应该进入你的大脑,因为它所做的只是浪费你的时间。)

  2. 你在装配以外的事情上做了一些时间关键的事情,并且仍然担心i++; i++;是更快还是i += 2 ...如果真的这很关键,你会在装配工作而不是浪费时间担心这一点。 (即便如此,这个特殊的例子很可能无关紧要。)

  3. 你有一个预感,有一件事可能比另一件事快一点,但你需要查一查。例如,如果有什么事情让你对StopWatch更快或Environment.TickCount感到烦恼,那就是过早优化,因为如果差异更大,你可能会更加确定并且不需要查看它起来。

  4. 如果您猜测某些事情可能会很慢,但您不太确定,只需发表//NOTE: Performance?评论,如果您以后遇到瓶颈,请在代码中检查这些地点。我个人并不担心不太明显的优化;如果需要,我稍后会使用一个分析器。

    另一种技巧:

    我只是运行我的程序,随机使用调试器进入程序,并查看它停止的位置 - 停止的地方可能是瓶颈,并且停止的次数越多,瓶颈就越严重。它几乎像魔术一样工作。 :)

答案 1 :(得分:4)

这句谚语(我相信)并不是指在创建好的设计时内置的优化。它指的是专门针对绩效的任务,否则将不会进行。

根据共同的智慧,这种优化不会“变得”过早 - 在被证明是无辜的之前它是有罪的。

答案 2 :(得分:4)

优化是使现有代码更有效地运行(更快的速度和/或更少的资源使用)的过程

如果程序员没有证明有必要,

所有优化都为时过早。 (例如,通过运行代码来确定它是否在可接受的时间范围内实现了正确的结果。这可能就像运行它以“查看”它是否运行得足够快,或者在分析器下运行以更仔细地分析它一样简单)

有好几个阶段可以很好地编程:

1)设计解决方案并选择一个优秀,高效的算法

2)以可维护,编码良好的方式实施解决方案。

3)测试解决方案,看它是否符合您对速度,RAM使用等的要求(例如“当用户点击”保存“时,是否需要不到1秒?”如果需要0.3秒,你真的不需要花一个星期来优化它来将时间缩短到0.2秒)

4) IF 它不符合要求,请考虑原因。在大多数情况下,这意味着转到步骤(1)以找到更好的算法,因为您可以更好地理解问题。 (编写快速原型通常是一种很便宜的探索方法)

5) IF 它仍然不符合要求,开始考虑可能有助于加速运行时的优化(例如,查找表,缓存等)。为了推动这一过程,性能分析通常是一个重要的工具,可以帮助您找到代码中的瓶颈和低效率,这样您就可以在代码上花费最多的时间。

我应该指出,一个经验丰富的程序员在处理一个相当熟悉的问题时可能能够在心理上跳过第一步,然后只应用一个模式,而不是每次都经历这个过程,但这只是一个简短的过程通过经验获得的切割

因此,有许多“优化”经验丰富的程序员将自动构建到他们的代码中。这些不是“过早优化”,而是“常识效率模式”。这些模式快速且易于实现,但大大提高了代码的效率,您无需进行任何特殊的时序测试来确定它们是否有益:

  • 不将不必要的代码放入循环中。 (类似于从现有循环中删除不必要代码的优化,但它不涉及两次编写代码!)
  • 将中间结果存储在变量中,而不是一遍又一遍地重新计算。
  • 使用查找表提供预先计算的值,而不是动态计算它们。
  • 使用适当大小的数据结构(例如,以字节(8位)而不是长(64位)存储百分比将使用8倍的RAM)
  • 使用预先绘制的图像绘制复杂的窗口背景,而不是绘制大量单个组件
  • 将压缩应用于您打算通过低速连接发送的数据包,以最大限度地减少带宽使用。
  • 以一种风格绘制网页图像,使您可以使用可获得高质量和高压缩效果的格式。
  • 当然,虽然技术上不是“选择”,但首先选择正确的算法!

例如,我刚刚在项目中替换了一段旧代码。我的新代码没有以任何方式“优化”,但(与原始实现不同)它的编写效率考虑在内。结果:我的运行速度提高了25倍 - 只是不浪费。我可以优化它以使其更快吗?是的,我可以轻松获得另外2倍的加速。我会优化我的代码以使其更快吗?不 - 速度提高5倍就足够了,我已经达到了25倍。此时的进一步工作只会浪费宝贵的编程时间。 (但如果要求发生变化,我可以在将来重新审视代码)

最后,最后一点:您工作的区域决定了您必须遇到的酒吧。如果您正在为游戏编写图形引擎或为实时嵌入式控制器编写代码,您可能会发现自己正在进行大量优化。如果您正在编写像记事本这样的桌面应用程序,只要您不会过度浪费,就可能永远不需要优化任何内容。

答案 3 :(得分:3)

在您知道有必要进行权衡之前,过早优化是以代码的其他一些正面属性(例如可读性)为代价进行性能优化。

通常在开发过程中进行过早优化,而不使用任何分析工具来查找代码中的瓶颈。在许多情况下,优化将使代码难以维护,有时还会增加开发时间,从而增加软件的成本。更糟糕的是......一些过早的优化结果不会使代码变得更快,在某些情况下甚至会使代码变得比以前慢。

答案 4 :(得分:3)

刚开始时,只交付产品比优化更重要。

随着时间的推移,您将分析各种应用程序,并将学习编码技巧,这些技能自然会导致优化的代码。基本上在某些时候,您将能够发现潜在的故障点并相应地构建事物。

但是,在发现实际问题之前不要出汗。

答案 5 :(得分:1)

当你的编码经验少于10年时。

答案 6 :(得分:1)

拥有(很多)经验可能是一个陷阱。我知道很多非常有经验的程序员(C \ C ++,汇编),他们往往担心太多,因为他们习惯于担心时钟滴答和多余的位。

嵌入式或实时系统等领域确实很重要,但在常规的OLTP / LOB应用程序中,您的大部分工作都应该针对可维护性,可读性和可变性。

答案 7 :(得分:1)

优化很棘手。请考虑以下示例:

  1. 决定实施两个服务器,每个服务器都有自己的工作,而不是实现一个可以完成这两项工作的服务器。
  2. 出于性能原因,决定使用一个DBMS而不是另一个DBMS。
  3. 出于性能原因,决定在有标准时使用特定的非可移植API(例如,当您基本需要标准JPA时使用特定于Hibernate的功能)。
  4. 出于性能原因在程序集中编写内容。
  5. 出于性能原因展开循环。
  6. 写一段非常快速但又模糊不清的代码。
  7. 我的底线很简单。优化是一个广义的术语。当人们谈论过早优化时,他们并不意味着你需要在不考虑完整图片的情况下做出第一件事。他们说你应该:

    1. 专注于80/20规则 - 不要考虑所有可能的情况,但最可能的情况。
    2. 没有任何充分的理由不要过度设计。
    3. 如果没有真正的,即时的性能问题,请不要编写不清晰,简单且易于维护的代码。
    4. 这真的归结为你的经历。如果您是图像处理方面的专家,并且有人要求您做过十次之前做过的事情,那么您可能会从一开始就推动所有已知的优化,但这没关系。过早优化是指在您不知道需要优化时尝试优化某些内容时。原因很简单 - 它有风险,浪费你的时间,而且可维护性较差。因此,除非您有经验并且之前已经走过这条路,否则如果您不知道有问题,请不要优化。

答案 8 :(得分:1)

请注意,优化不是免费的(如在啤酒中)

  • 编写
  • 需要更多时间
  • 需要更多时间阅读
  • 需要更多时间来测试
  • 调试需要更多时间
  • ...

所以在优化任何事情之前,你应该确定它是值得的。

您链接的Point3D类型似乎是某些东西的基石,优化的情况可能很明显。

就像.NET库的创建者在开始优化System.String之前不需要任何测量一样。他们不得不在此期间进行衡量。

但是大多数代码在最终产品的性能中并没有发挥重要作用。这意味着任何优化工作都会浪费掉。

除此之外,大多数“过早优化”都是未经测试/未测量的黑客攻击。

答案 9 :(得分:1)

如果您在实施的早期阶段花费太多时间设计优化,那么优化还为时过早。在早期阶段,您可以更好地担心:实现核心代码,编写单元测试,系统相互通信,UI以及其他任何内容。优化需要付出代价,您可能会浪费时间优化不需要的东西,同时创建难以维护的代码。

优化只有在您对项目有具体的性能要求时才有意义,然后在初始开发之后性能会很重要,并且您已经实施了足够的系统,以便实际测量您需要测量的任何内容。不测量就不要优化。

随着您获得更多经验,您可以轻松地进行早期设计和实施,以便进一步优化,也就是说,尝试以这样的方式进行设计,以便更轻松地衡量性能并在以后优化,如果甚至是必要的。但即使在这种情况下,您也应该在开发的早期阶段花费很少的时间进行优化。