码:
@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; }
字节代码:
>内联(更快):getstatic,invokestatic,invokevirtual,areturn
>静态归档(较慢):getstatic,areturn
>对象字段(较慢):aload,getfield,areturn
性能(使用Apache AB,单线程,多次运行,结果一致):
>内联:17078.29 [#/ sec](平均值)
>静态字段:5242.64 [#/ sec](平均值)
>对象字段:5417.40 [#/ sec](平均值)
环境:RHEL6 JDK Oracle 1.7.0_60-b19 64位
有可能JVM使用本机代码优化了内联版本,但从未考虑优化其他两个因为它们已经非常小了吗?
解决方法
相反,我想给你一个有根据的猜测,因为你的代码是应用costant folding的典型示例.当内联值而不是从字段读取时,JVM可以安全地假设该值是常量.当JIT编译该方法时,常量表达式因此可以安全地与您的框架代码合并,这可能导致更少的JIT可靠性,从而提高性能.对于字段值,即使是最终值,也不能假设常量值,因为字段值可以改变. (只要字段值不是编译时常量,基元或常量字符串,由javac内联.)因此,JVM可能不会对值进行常量折叠.
您可以在JMH的教程中注明read more on constant folding:
If JVM realizes the result of the computation is the same no matter what,it can cleverly optimize it. In our case,that means we can move the computation outside of the internal JMH loop. This can be prevented by always reading the inputs from the state,computing the result based on that state,and the follow the rules to prevent DCE.
我希望你使用这样一个框架.否则,您的性能指标不太可能有效.
通过读取字节代码,您通常无法了解运行时性能,因为JIT编译器可以在优化期间将字节代码调整为任何内容.字节代码布局应该只在解释代码时才重要,这通常不是将性能测量为性能关键的状态,热代码始终是JIT编译的.