【问题标题】:Should I inline long code in a loop, or move it in a separate method?我应该在循环中内联长代码,还是在单独的方法中移动它?
【发布时间】:2011-08-17 05:58:08
【问题描述】:

假设我有一个这样的循环(任何 while 或 for):

loop{
    A long code.
}

从时间复杂度来看,我是不是应该把这段代码分成几部分,在循环外写一个函数,反复调用那个函数?

我很久以前读过一些关于函数的东西,重复调用一个函数需要更多的时间或内存或类似的东西,我记不太清了。您能否也提供一些关于此类(时间复杂度、编码风格)的良好参考?

能否提供一些关于堆内存、开销等影响程序性能的参考书或教程?

【问题讨论】:

  • When to optimize。计算机速度越来越快。我的时间对我来说比 CPU 上的几个额外周期更有价值。虽然有许多环境具有硬性能限制,但它们是 1) 已知的; 2) 设计中的计划; 3) 支持基准/分析。
  • 提防premature optimization。然而,让你的代码整洁总是一个好习惯。
  • 请记住,具有短代码体的函数往往会在调用站点被 jit-ed 看到en.wikipedia.org/wiki/HotSpot
  • 另见this question 引用 Martin Fowler 的话:“这只需要精心设计的代码和小方法 - 从本质上讲,这使得 Hotspot 可以更好地优化并让 CPU 更有效地缓存运行时的代码。”

标签: java performance coding-style


【解决方案1】:

在这种情况下,性能差异可能非常小。在您确定这部分代码是一个严重的瓶颈之前,我会专注于清晰度而不是性能。

不过,这确实取决于您在循环中运行的代码类型。如果你只是在做一个不会占用任何 CPU 时间的微小数学运算,但你做了几十万次,那么内联计算可能是有意义的。不过,任何比这更贵的东西,性能都不成问题。

【讨论】:

  • 我的经验是,在 99% 的情况下,Java 编译器的优化比我为优化代码所做的任何事情都要好。 IE。类似于您所描述的内容可能会在编译器的优化过程中完成。 --> 寻找可读、可维护和可扩展的代码!
  • AFAIK,没有理由获得 any 性能。让 JIT 为您内联它。保持方法简短,以提高可读性和性能,因为 JIT 更适合短方法。
【解决方案2】:

调用函数有开销。

因此,如果“长代码”与此开销相比更快(并且您的应用程序关心性能),那么您绝对应该避免开销。

但是,如果性能没有明显变差,最好使用一个(或更好的多重)函数使其更具可读性。

【讨论】:

  • 不,通常没有开销,如果需要,JIT 可以轻松内联它。不要在这里避免更易读的性能代码,因为没有可衡量的收益。实际上,JIT 在较短的方法上效果更好!
【解决方案3】:

性能优化的规则之一:衡量它。

就我个人而言,我会先寻找可读的代码,然后在必要时对其进行优化。通常,没有必要:-)

CHAPTER 3 - Measurement Is Everything的第一行

“我们应该忘记小的效率,比如大约 97% 的时间: 过早的优化是万恶之源。”——Donald Knuth

在这种情况下,两种解决方案之间的性能差异可能很小,因此编写更清晰的代码是这样做的方法。

【讨论】:

    【解决方案4】:

    真的没有一个简单的关于性能的“教程”,它是一个非常复杂的主题,即使是经验丰富的老手也常常无法完全理解。无论如何,为了让您更多地了解“调用”函数的开销是什么,基本上您所做的是“冻结”函数的状态(在 Java 中没有“函数”本身,它们都是调用方法),调用方法,然后“解冻”,您的方法之前的位置。

    “冻结”本质上包括将状态信息(您在方法中的位置、变量的值等)推送到堆栈,“解冻”包括将保存的状态从堆栈中弹出并更新控制结构到调用函数之前它们所在的位置。自然,内存操作远非免费,但 VM 非常擅长将性能影响降至最低。

    现在请记住,Java 几乎完全基于堆,唯一真正需要压入堆栈的是指针的值(小)、您在程序中的位置(再次小)以及您拥有的任何原语您的方法的本地化,以及一点点控制信息,仅此而已。此外,虽然你不能在 Java 中显式内联(尽管我确信那里有字节码编辑器基本上可以让你这样做),但大多数 VM,包括最流行的 HotSpot VM,都会自动为你做这件事。 http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html

    所以底线几乎是 0 性能影响,如果您想自己验证,您可以随时运行基准测试和分析工具,他们应该能够为您确认。

    【讨论】:

      【解决方案5】:

      执行速度的角度来看,这无关紧要,如果您仍然认为这是一个瓶颈,则很容易衡量。

      开发性能的角度来看,保持代码简短是个好主意。我会投票赞成将循环内容转换为一个(或多个)正确命名的方法。

      【讨论】:

        【解决方案6】:

        算了!您无法通过 JIT 的工作获得任何性能。让 JIT 为您内联它。保持方法简短,以提高可读性和性能,因为 JIT 更适合短方法。

        有些微优化可能会帮助您获得一些性能,但请不要考虑它们。我建议以下规则:

        • 使用适当的对象和算法编写干净的代码以提高可读性和性能。
        • 如果程序太慢,请分析并识别关键部分。
        • 考虑使用更好的对象和算法来改进它们。
        • 作为最后的手段,您还可以考虑进行微优化。

        【讨论】:

          猜你喜欢
          • 2021-12-06
          • 1970-01-01
          • 2010-12-14
          • 1970-01-01
          • 2017-06-13
          • 1970-01-01
          • 2021-01-05
          • 2019-02-28
          • 2019-01-28
          相关资源
          最近更新 更多