我应该在循环中内联长代码,还是在单独的方法中移动它?

时间:2011-08-17 05:58:08

标签: java performance coding-style

假设我有一个循环(任何while或for)如下:

loop{
    A long code.
}

从时间复杂度来看,我应该将这些代码分成几部分,在循环外写一个函数,然后重复调用该函数吗?

我很久以前就读过一些关于函数的东西,重复调用函数会花费更多的时间或内存或类似的东西,我不记得它。您是否也可以提供一些关于此类事件的好参考(时间复杂度,编码风格)?

您是否也可以提供一些关于堆内存,开销等的参考书或教程,这会影响程序的性能?

6 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:1)

调用函数会产生开销。

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

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

答案 2 :(得分:1)

表现优化的第一条规则:衡量它。

就个人而言,我首先考虑可读代码,然后在必要时进行优化。通常,没有必要: - )

请参阅CHAPTER 3 - Measurement Is Everything

中的第一行
  

“我们应该忘记效率低,大约97%的时间说:   过早优化是万恶之源。“ - 唐纳德克努特

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

答案 3 :(得分:1)

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

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

现在请记住,Java几乎完全是基于堆的,唯一真正需要推送到堆栈的东西是指针的值(小),你在程序中的位置(再次小),以及你有什么原语您的方法本地化,以及一小部分控制信息,没有别的。此外,尽管您无法在Java中明确内联(虽然我确信那里有字节码编辑器基本上允许您这样做),但大多数虚拟机(包括最流行的HotSpot VM)都会自动为您执行此操作。 http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

算了吧!通过完成JIT的工作,你无法获得任何表现。让JIT为您内联。保持方法的简洁性以便于阅读和性能,因为JIT在短方法下效果更好。

有一些微型化可能会帮助您获得一些性能,但甚至不会考虑它们。我建议遵守以下规则:

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