Java中的冗余编程是否效率低下?

时间:2018-03-10 11:19:07

标签: java performance compilation

例如,我有3个调用一个方法(总是3个调用),我需要将1传递给方法,第一个调用2用于第二个,3个用于第三个调用。我可以用两种方式解决这个问题。使用1,2,3进行3次调用或使用for循环。

call(1);
call(2);
call(3);

for (int i = 1; i <= 3; i++) {
    call(i);
}

问题是什么会跑得更快。据我所知,这完全取决于Java编译器,因为它可以在for循环上进行优化。

在普通的C中,我认为冗余方式会快一点,因为增量和比较不需要计数器。

2 个答案:

答案 0 :(得分:2)

对此没有明确的答案。它取决于您使用的Java版本,运行它的平台,运行它的频率(例如,代码是否是JIT编译),等等。

但是,我们可以说即使JIT编译器优化器没有展开循环,两个版本之间执行时间的差异也只有几个纳秒< / strong>在现代CPU上。这不太可能对您的应用程序的整体性能产生明显的影响。

我的建议是不要花时间尝试在此级别上加快代码速度。

  • 花时间让它上班。
  • 一旦它正常工作,对它进行基准测试并确定它是否足够快。
  • 如果且仅时速度不够快:
    1. 使用分析器查找热点
    2. 优化热点
    3. 重新运行基准以确定您的优化是否有帮助
    4. 重复......直到你看不到热点,或者它足够快。

答案 1 :(得分:1)

我假设“冗余”是指你手动写出所有函数调用而不是循环。

在效率方面 - 是的,冗余效率低下,但不是因为你可能会想到的原因。它在维护成本和代码/文件大小膨胀方面效率低下。

例如,您现在有3个函数调用,有3个整数。稍后您可能决定需要将其调用20次,并且使用冗余方法,这涉及使用新整数复制行17次。

现在您决定需要更改当前传入的整数。因此,您必须更新所有20个整数。

接下来你决定需要在每个函数调用之间插入一些逻辑,所以你要写一次并复制+粘贴20次。

这种扩展性极差,增加了文件的大小(字节大小),并且容易出错。如果事实证明你在函数之间添加的逻辑存在错误,那么现在你可以在20个不同的地方修复相同的错误。

你获得的任何加速都可能会被忽略,因为你的代码变成了一个可怕的,无法维护的怪物。

您可能想要查看的是这种称为 循环展开 的更有限的形式。这可以通过手工完成,如评论中所指出的,JIT编译器确定它确实值得。它针对您使用for循环同时具有计数器和逻辑比较引发的问题,这会引入一些开销。我们的想法是,您尝试在每个循环期间执行尽可能多的计算,并因此执行更少的循环。

简单示例:

for (int i = 1; i <= 300; i += 3) {
    call(i);
    // some logic
    call(i + 1);
    // some logic
    call(i + 2);
    // some logic
}

现在你在循环中调用相同的函数3次并循环100次,但结果是300次函数调用。这可能比在循环中具有1个函数调用更有效,并且它的可伸缩性更高。