Java null检查性能

时间:2018-06-08 06:58:14

标签: java performance performance-testing

我想知道在使用直接比较或使用Objects.isNull()方法检查java中的对象是否为null时是否存在任何显着差异。

public class Test {

  public final static Long ITERATIONS = 100000000L; 

  @Test
  public void noFnCalls() {
    balong startTime = System.currentTimeMillis();
    Object x = new Object();
    Long i;
    for (i = 0L; i < ITERATIONS; i++) {
      boolean t = x == null;
    }
    long estimatedTime = System.currentTimeMillis() - startTime;
    System.out.println("noFnCalls ellapsed time: " + estimatedTime);
  }

  @Test
  public void withFnCalls() {
    long startTime = System.currentTimeMillis();
    Object x = new Object();
    Long i;
    for (i = 0L; i < ITERATIONS; i++) {
      boolean t = Objects.isNull(x);
    }
    long estimatedTime = System.currentTimeMillis() - startTime;
    System.out.println("withFnCalls ellapsed time: " + estimatedTime);
  }
}

令人惊讶的是,至少在我看来,总是花费更多的时间来完成&#34; noFnCalls&#34;。我期待相反的结果,因为它导致使用堆栈进行方法调用。

这是输出:(每次都会改变,很明显,但总是用&#34; noFnCalls&#34;更高)

  

noFnCalls经过的时间:583

     

withFnCalls经过时间:463

为什么会产生这种情况?

1 个答案:

答案 0 :(得分:4)

您看到的结果可能是由于首先运行“noFnCalls”,而没有在测试和测量之前引入适当的预热。

我明白了:

withFnCalls ellapsed time: 444
noFnCalls ellapsed time: 471
withFnCalls ellapsed time: 334
noFnCalls ellapsed time: 331
withFnCalls ellapsed time: 330
noFnCalls ellapsed time: 325
withFnCalls ellapsed time: 331
noFnCalls ellapsed time: 326
withFnCalls ellapsed time: 326
noFnCalls ellapsed time: 328

使用

import java.util.Objects;

public class Test {

  public final static Long ITERATIONS = 100000000L; 

  public static void main(String args[]) {
    withFnCalls();
    noFnCalls();
    withFnCalls();
    noFnCalls();
    withFnCalls();
    noFnCalls();
    withFnCalls();
    noFnCalls();
    withFnCalls();
    noFnCalls();
  }
  public static void noFnCalls() {
    long startTime = System.currentTimeMillis();
    Object x = new Object();
    Long i;
    for (i = 0L; i < ITERATIONS; i++) {
      boolean t = x == null;
    }
    long estimatedTime = System.currentTimeMillis() - startTime;
    System.out.println("noFnCalls ellapsed time: " + estimatedTime);
  }

  public static void withFnCalls() {
    long startTime = System.currentTimeMillis();
    Object x = new Object();
    Long i;
    for (i = 0L; i < ITERATIONS; i++) {
      boolean t = Objects.isNull(x);
    }
    long estimatedTime = System.currentTimeMillis() - startTime;
    System.out.println("withFnCalls ellapsed time: " + estimatedTime);
  }
}

withFnCalls ellapsed time: 3618
noFnCalls ellapsed time: 3361
withFnCalls ellapsed time: 3445
noFnCalls ellapsed time: 3278
withFnCalls ellapsed time: 3350
noFnCalls ellapsed time: 3292
withFnCalls ellapsed time: 3309
noFnCalls ellapsed time: 3262
withFnCalls ellapsed time: 3293
noFnCalls ellapsed time: 3261

如果我增加到1000000000L次迭代。这是通过Oracle使用Java 9 64位服务器jvm(内置9 + 181)完成的,在Windows 10上使用具有Intel i5-2600 cpu的计算机运行。

就像其他人所说的那样,微基准测试是 hard ,很多不同的事情会影响结果。你不应该在这些测试中得出结论。这种测试并没有真正说明 - 任何差异都很容易在彼此非常接近的噪声测量代码中丢失。

关于java中微基准测试的强制推荐线程:How do I write a correct micro-benchmark in Java?