6

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

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

在那里他谈到了他为实现他的应用程序所需的类型而做出的决定。

如果是我,谈论这些我们需要编写的代码,其他程序员会认为:

  1. 当什么都没有并因此过早地优化时,我想得太远了。
  2. 在没有减速或性能问题的情况下过度思考无关紧要的细节。

或两者。

并建议只是实施它,而不是担心这些,直到它们成为问题。

哪个更优惠?

在完成任何实施之前,如何区分性能关键型应用程序的过早优化和明智决策?

4

10 回答 10

13

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

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

  2. 您在组装以外的其他事情中做一些时间紧迫的事情,并且仍然担心是否i++; i++;更快或者i += 2......如果它真的那么关键,那么您将在组装中工作而不是浪费时间担心这个。(即使那样,这个特定的例子也很可能无关紧要。)

  3. 你有一种预感,一件事可能比另一件事快一点,但你需要查一下。例如,如果有什么东西让你烦恼StopWatch是更快还是Environment.TickCount,这是过早的优化,因为如果差异更大,你可能会更确定并且不需要查找它。

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

另一种技术:

我只是运行我的程序,用调试器随机闯入它,看看它在哪里停止——它停止的地方可能是一个瓶颈,它停在那里的次数越多,瓶颈就越严重。它几乎像魔术一样工作。:)

于 2011-01-28T20:23:12.847 回答
4

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

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

编程好有几个阶段:

1) 设计解决方案并选择一个好的、高效的算法

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

3) 测试解决方案,看看它是否满足您对速度、RAM 使用等的要求(例如“当用户点击“保存”时,是否需要不到 1 秒?”如果需要 0.3 秒,你真的不'无需花费一周时间对其进行优化以将时间缩短到 0.2 秒)

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

5)如果仍然不满足要求,开始考虑可能有助于加快运行时的优化(例如,查找表、缓存等)。为了推动这个过程,分析通常是帮助您定位代码中的瓶颈和低效率的重要工具,因此您可以在代码上花费的时间获得最大收益。

我应该指出,处理一个相当熟悉的问题的有经验的程序员可能能够在精神上跳过第一步,然后只应用一个模式,而不是每次都在物理上经历这个过程,但这只是一个捷径,即通过经验获得

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

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

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

最后一点:你工作的领域决定了你必须达到的标准。如果您正在为游戏编写图形引擎或为实时嵌入式控制器编写代码,您可能会发现自己做了很多优化。如果您正在编写像记事本这样的桌面应用程序,那么您可能永远不需要优化任何东西,只要您不过分浪费。

于 2011-01-29T09:54:39.260 回答
4

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

根据常识,这种优化不会“变得”为时过早——在被证明是无辜的之前,它是有罪的。

于 2011-01-28T20:25:38.337 回答
3

过早的优化是在您知道有必要做出这种权衡之前,以牺牲代码的其他一些积极属性(例如可读性)为代价来进行性能优化。

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

于 2011-01-28T20:18:23.007 回答
3

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

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

但是,在您发现实际问题之前不要担心。

于 2011-01-28T20:24:23.823 回答
1

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

  1. 决定实现两台服务器,每台服务器都做自己的工作,而不是实现一个服务器来完成这两项工作。
  2. 出于性能原因,决定使用一个 DBMS 而不是另一个。
  3. 出于性能原因,在有标准时决定使用特定的、不可移植的 API(例如,当您基本上需要标准 JPA 时使用特定于 Hibernate 的功能)。
  4. 出于性能原因在汇编中编码某些东西。
  5. 出于性能原因展开循环。
  6. 编写一段非常快速但晦涩难懂的代码。

我的底线很简单。优化是一个广义的术语。当人们谈论过早优化时,他们并不意味着您只需要做第一件事而不考虑整体情况。他们说你应该:

  1. 专注于 80/20 规则——不要考虑所有可能的情况,而要考虑最可能的情况。
  2. 不要在没有任何充分理由的情况下过度设计东西。
  3. 如果没有真正的、直接的性能问题,不要编写不清晰、简单且易于维护的代码。

这一切都归结为您的经验。如果你是图像处理方面的专家,并且有人要求你做你之前做过十次的事情,你可能会从一开始就推动所有已知的优化,但这没关系。过早的优化是当您尝试优化某些东西时,您不知道它需要从一开始就进行优化。原因很简单——它有风险,浪费你的时间,而且更难维护。因此,除非您有经验并且您以前曾走过这条路,否则如果您不知道存在问题,请不要进行优化。

于 2011-01-28T20:34:07.657 回答
1

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

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

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

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

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

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

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

于 2011-01-28T20:36:01.257 回答
1

如果您在实施的早期阶段花费太多时间来设计优化,那么优化还为时过早。在早期阶段,您需要担心一些更好的事情:实现核心代码、编写单元测试、系统相互通信、UI 等等。优化是有代价的,你很可能在优化一些不需要的东西上浪费时间,同时创建更难维护的代码。

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

随着您获得更多经验,您可以在早期的设计和实现中关注未来的优化,也就是说,尝试以一种更容易衡量性能并在以后进行优化的方式进行设计,如果这甚至是必要的. 但即使在这种情况下,您也应该在开发的早期阶段花很少的时间进行优化。

于 2011-01-29T00:14:24.427 回答
1

当您拥有不到 10 年的编码经验时。

于 2011-01-28T20:20:15.707 回答
1

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

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

于 2011-01-28T20:23:55.427 回答