什么JVM优化导致这些性能结果?
执行Java REST服务性能测试我发现一个意外的模式:在每次调用中创建并返回始终相同的值对象的方法运行得比另一个只返回存储在类或对象字段中的值对象的版本快。
码:
@POST @Path("inline") public Response inline(String s) {
return Response.status(Status.CREATED).build();
}
private static final Response RESP = Response.status(Status.CREATED).build();
@POST @Path("staticfield") public Response static(String s) {
return RESP;
}
private final Response resp = Response.status(Status.CREATED).build();
@POST @Path("field") public Response field(String s) {
return resp;
}
字节码:
性能 (使用Apache AB,单线程,多次运行,结果一致):
环境 :RHEL6 + JDK Oracle 1.7.0_60-b19 64位
JVM有可能使用本地代码优化了内联版本,但从来没有考虑优化其他两个版本,因为它们已经很小了?
正如评论中指出的那样,如果没有真正看待大会,很难说清楚。 由于同期使用的是REST框架,不过我认为从程序集中很难判断出有相当多的代码需要阅读。
相反,我想给你一个有根据的猜测,因为你的代码是应用costant折叠的典型例子。 当一个值被内联并且不从字段读取时,JVM可以安全地假定这个值是常量。 当JIT编译该方法时,常量表达式因此可以安全地与您的框架代码合并,从而可能导致组装JIT的不足,从而提高性能。 对于字段值,即使是final
一个字段值,由于字段值可能会更改,因此无法假定常量值。 (只要字段值不是编译时间常量,就是由javac内联的原始String
或常量String
)。因此,JVM可能不会不断折叠该值。
你可以阅读更多关于JMH教程中的常量折叠的地方:
如果JVM实现计算的结果是相同的,无论如何,它可以巧妙地优化它。 在我们的例子中,这意味着我们可以将计算移到内部JMH循环之外。 通过始终读取状态的输入,根据该状态计算结果并遵循防止DCE的规则,可以防止这种情况发生。
我希望你使用了这样的框架。 否则,您的绩效指标不太可能有效。
从阅读字节码,你通常不会学习太多的运行时性能,因为JIT编译器可以在优化期间将字节码调整为任何东西。 字节代码布局应该只在解释代码时才重要,因为性能至关重要,热代码始终是JIT编译的,因此这通常不是测量性能的状态。
链接地址: http://www.djcxy.com/p/21899.html上一篇: What JVM optimization is causing these performance results?