基准测试可能需要编译器优化

时间:2014-07-06 15:01:18

标签: java optimization benchmarking javac

我开发了一个小型库,可以使用注释进行声明性参数验证,如下所示:

@Validate({"not null | number"})
public static Integer notNullAnnotated(Integer number) {
    return number++;
}

现在我正在对纯Java代码版本进行基准测试:

public static Integer notNullInline(Integer number) {
    if (number != null) {
        return number++;
    } else {
        throw new IllegalArgumentException("argument should not be null");
    }
}

这是测试:

@Test
public void performanceTest() {
    long time = System.nanoTime();
    for (int i = 0; i < iterationCount; i++) {
        notNullAnnotated(i);
    }
    System.out.println("time annotated : " + (System.nanoTime() - time));

    time = System.nanoTime();
    for (int i = 0; i < iterationCount; i++) {
        notNullInline(i); // TODO does compiler do any optimization here?
    }
    System.out.println("time inline : " + (System.nanoTime() - time));
}

我知道这不是进行基准测试的预期方式。现在我宁愿避免为这个简单的测试添加任何实用程序库(因为即使这样结果也很好),但是我想知道编译器是否在这里进行了任何优化?

2 个答案:

答案 0 :(得分:2)

由于您已经远远落后于过早的优化路径,请查看Hotspot的PrintAssemblyCompileThreshold标志。第一个选项允许您检查Hotspot生成的程序集。第二个允许您设置JIT启动时的阈值。

答案 1 :(得分:1)

当然,及时编译器将优化您的代码(假设迭代计数相当高),就像在运行该代码的实际程序中一样。因此,在基准测试中,优化本身是可取的。当然,如果代码的人为性质允许实际代码不可用的优化,那么您将遇到问题。在您的情况下,编译器可能会断定notNullInline永远不会抛出,因此没有效果,并选择删除整个循环。

How do I write a correct micro-benchmark in Java?

已经讨论过编写正确的基准