哪个更快?

时间:2011-02-22 05:40:27

标签: java while-loop performance

我想知道以下哪一项会更好地执行,只是出于好奇。语言是Java。

int num = -500;
int num2 = 0;

while( Math.abs(num) > num2 )
    num2 ++;

int num = -500;
int num2 = 0;
num = Math.abs(num);

while( num > num2 )
    num2 ++;

基本上我想知道' Math.abs'是为while循环的每次迭代调用,还是在后台进行一些代码优化?

谢谢!

7 个答案:

答案 0 :(得分:5)

Math.abs()就是所谓的pure function,所以一个非常好的编译器理论上可以优化它。有专门设计的函数式编程语言可以做到这一点,但在Java中很难。

第二个不仅可以编译成更快的代码,它通常被认为是更好的风格,因为它更清楚地说明了循环中实际变化的内容以及没有变化的内容。

答案 1 :(得分:3)

是的,每次迭代都会调用Math.abs(num),因为Java永远不会告诉或猜测返回值取决于参数。

对于Java,该方法与Math.random()“相等”。

所以第一个例子使用了更多的CPU时间。

答案 2 :(得分:1)

出于好奇,我执行了一个不科学的基准测试,返回了以下结果:

为了可比性:

  • 热身次数([1]):1000
  • 迭代次数([1]):1500
  • 删除的异常值的数量([1]):300
  • 显示具有95%可支持性的CI的错误栏 [1]针对每个解决方案和比例级别

主机信息:

  • Java版本:1.6.0_21
  • Java供应商:Sun Microsystems Inc.
  • Java VM参数:-Xmx1024m; -Dfile.encoding =的Cp1252
  • OS架构:amd64
  • 操作系统名称:Windows 7
  • 操作系统版本:6.1
  • 可用内核:2
  • JVM可用的可用内存(字节):122182232
  • 最大内存(字节):954466304
  • 使用的总内存(字节):124125184

答案 3 :(得分:0)

第二个必须在while循环的每次传递中执行绝对值函数。当然,只有当Java不再优化存储这样的操作结果时才会出现这种情况,我相信情况就是如此。 Java暂时还没有优化,它现在依赖于JIT。

所以回答你的问题,第一个更快。

答案 4 :(得分:0)

Java代码

package test;

public class SpeedTest 
{
    public void first()
    {
        int num = -500;
        int num2 = 0;

        while( Math.abs(num) > num2 )
            num2 ++;
    }

    public void second()
    {
        int num = -500;
        int num2 = 0;
        num = Math.abs(num);

        while( num > num2 )
            num2 ++;
    }
}

字节代码

Compiled from "SpeedTest.java"
public class test.SpeedTest extends java.lang.Object{
public test.SpeedTest();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public void first();
  Code:
   0:   sipush  -500
   3:   istore_1
   4:   iconst_0
   5:   istore_2
   6:   goto    12
   9:   iinc    2, 1
   12:  iload_1
   13:  invokestatic    #15; //Method java/lang/Math.abs:(I)I
   16:  iload_2
   17:  if_icmpgt       9
   20:  return

public void second();
  Code:
   0:   sipush  -500
   3:   istore_1
   4:   iconst_0
   5:   istore_2
   6:   iload_1
   7:   invokestatic    #15; //Method java/lang/Math.abs:(I)I
   10:  istore_1
   11:  goto    17
   14:  iinc    2, 1
   17:  iload_1
   18:  iload_2
   19:  if_icmpgt       14
   22:  return
}

从上面两者基本上都是〜20指令。如果你非常挑剔,那么第一个很快。

区别的原因是您正在计算并将结果存储在第二种方法中。您需要在比较时再次弹出。在第一种情况下,您直接比较Math.abs之后的寄存器值。并且因此两个额外的指令。

<小时/> 的更新

As pointed out by @ide and @bestsss:

  

中的指令数量   字节码并不真正与之相关   他们实际上的次数   调用。还有HotSpot来加香料   事情进一步发展(如死代码   优化)。

在此示例中,Math.abs()在固定值-500时调用。因此,HotSpot JVM可以对其进行优化。

有关详细信息,请参阅以下注释。

答案 5 :(得分:0)

class AbsTest {

   public static void main(String[] args) {
       int num = -2000000000;
       int num2 = 0;



       long then = System.currentTimeMillis();
       while( Math.abs(num) > num2 )
           num2 ++;

       long then2 = System.currentTimeMillis();
       num = Math.abs(num);
       num2 = 0;

       while( num > num2 )
           num2 ++;

       long now = System.currentTimeMillis();
       System.out.println(then2 - then); // first time
       System.out.println(now - then2); // second time

   }

}

结果:

C:\Documents and Settings\glowcoder\My Documents>java AbsTest
2953
1828

C:\Documents and Settings\glowcoder\My Documents>

答案 6 :(得分:0)

Hey Inventor我认为将这两者进行比较是没有价值的,因为它取决于您的编译器实现。正如

  1. 如果您的编译器执行优化,那么您发现两个代码很可能会占用相同的运行时间。

  2. 如果它没有执行那么显然第二个更快。

  3. 所以我认为你不应该担心这些事情。