在基准测试中可能存在不必要的编译器优化



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

@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));
}

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

既然您已经在过早的优化路径上走了这么远,请查看Hotspot的PrintAssemblyCompileThreshold标志。第一个选项允许您检查Hotspot生成的程序集。第二个选项允许您设置JIT何时启动的阈值。

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

如何在Java中编写正确的微基准测试已经讨论过了?

相关内容

  • 没有找到相关文章

最新更新