Java 基准测试中可能不需要的编译器优化

Java 基准测试中可能不需要的编译器优化,java,optimization,benchmarking,javac,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)

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

@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));
}
@测试
公共空间绩效测试(){
长时间=System.nanoTime();
for(int i=0;i

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

既然您已经走上了过早优化的道路,请查看热点的
printpassembly
CompileThreshold
标志。第一个选项用于检查部件热点生成。第二个选项允许您设置JIT开始的阈值。

由于您已经走上了过早优化的道路,请查看Hotspot的
PrintAssembly
CompileThreshold
标志。第一个选项用于检查部件热点生成。第二个选项允许您设置JIT开始的阈值。

由于您已经走上了过早优化的道路,请查看Hotspot的
PrintAssembly
CompileThreshold
标志。第一个选项用于检查部件热点生成。第二个选项允许您设置JIT开始的阈值。

由于您已经走上了过早优化的道路,请查看Hotspot的
PrintAssembly
CompileThreshold
标志。第一个选项用于检查部件热点生成。第二个选项允许您设置JIT开始的阈值。

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


编写正确的基准已经在

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


编写正确的基准已经在

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


编写正确的基准已经在

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



编写一个正确的基准已经在

done上讨论过了,compileThreshold似乎有一些影响,现在效果更好了。我是否可以禁用任何优化(例如禁用JIT)?(使用Java8JDK)您可以通过在命令中添加
-Djava.compiler=NONE
来禁用JIT。但这使得测试非常人为;你永远不会在生产中运行它。我通常希望在基准测试中进行优化,这样它们至少能够代表正在发生的事情。
-XJava.compiler=NONE
-Xint
有什么不同吗?我总是使用后一个标志来禁用JITC,不知道前一个存在…-X标志是特定于JVM的。J9可能支持设置java.compiler。除此之外,我不确定.Oops的意思是
-DJava.compiler=NONE
,但我想你明白了。不知道
-X
标志是VM特有的;谢谢你!。看起来从现在起我将使用的是
-D
版本,compileThreshold似乎有一些影响,现在效果更好了。我是否可以禁用任何优化(例如禁用JIT)?(使用Java8JDK)您可以通过在命令中添加
-Djava.compiler=NONE
来禁用JIT。但这使得测试非常人为;你永远不会在生产中运行它。我通常希望在基准测试中进行优化,这样它们至少能够代表正在发生的事情。
-XJava.compiler=NONE
-Xint
有什么不同吗?我总是使用后一个标志来禁用JITC,不知道前一个存在…-X标志是特定于JVM的。J9可能支持设置java.compiler。除此之外,我不确定.Oops的意思是
-DJava.compiler=NONE
,但我