java - 哪些 JVM 优化导致了这些性能结果?

标签 java performance jvm bytecode microbenchmark

<分区>

在 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; 
}

字节码:

  • 内联(更快):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 64bits

JVM 是否有可能使用 native 代码优化了内联版本,但从未考虑过优化其他两个,因为它们已经非常小了?

最佳答案

正如评论中所指出的,如果不实际查看程序集就很难分辨。由于您使用的是 REST 框架,因此我认为很难从程序集中分辨出来,因为有相当多的代码需要阅读。

相反,我想给你一个有根据的猜测,因为你的代码是应用 costant folding 的典型示例。 .当一个值被内联而不是从字段中读取时,JVM 可以安全地假定该值是常量。当 JIT 编译该方法时,常量表达式因此可以安全地与您的框架代码合并,这可能会导致更少的 JIT 组装,从而提高性能。对于字段值,即使是 final 值,也不能假定为常量值,因为字段值可以更改。 (只要字段值不是编译时间常量、原始类型或常量String,它们由javac 内联。)因此,JVM 可能无法不断折叠该值。

您可以 read more on constant foldingJMH 的教程中指出的地方:

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 编译的。

关于java - 哪些 JVM 优化导致了这些性能结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24960771/

相关文章:

performance - Spark : why is a subselect with "NOT IN" dramatically slower than "IN"?

java - 智能 JVM 和 JIT 微优化

multithreading - 数量逻辑 CPU 是否会影响 Java8 Streams 性能?

java - 将对象的信息传递给另一个 Activity

java - 在 Java 8 中仅使用 Function<> 实现 compose

java - ArrayList 上加载对象的错误逻辑(该列表有多个具有相同数据的对象)

mysql删除效率

performance - OCaml 异常的表现

java - 如果-XX :+UseCodeCacheFlushing is not used? 是否会刷新JVM中的CodeCache

java - 迭代 POJO 属性