Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What JVM optimization is causing these performance results? [closed]

In a Java REST service performance test, I got an unexpected pattern: a method that creates and returns always the same value object in each invocation runs faster than another version that just returns the value object stored in a class or object field.

Code:

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

Byte code:

  • Inline (faster): getstatic, invokestatic, invokevirtual, areturn
  • Static filed (slower): getstatic, areturn
  • Object field (slower): aload, getfield, areturn

Performance (using Apache AB, single thread, several runs with consistent results):

  • Inline: 17078.29 [#/sec] (mean)
  • Static field: 5242.64 [#/sec] (mean)
  • Object field: 5417.40 [#/sec] (mean)

Environment: RHEL6 + JDK Oracle 1.7.0_60-b19 64bits

Is is possible that the JVM optimized the inline version with native code, but never considered optimizing the other two because they are already pretty small?

like image 529
Sebastian Avatar asked Jul 25 '14 16:07

Sebastian


People also ask

What is JVM optimization?

JVM tuning mainly involves optimizing the garbage collector for better collection performance so that applications running on VMs can have a larger throughput while using less memory and experiencing lower latency.

What is JVM performance?

Java virtual machine tuning is the process of adjusting the default parameters to match our application needs. This includes simple adjustments like the size of the heap, through choosing the right garbage collector to using optimized versions of getters.

Does JVM optimize code?

The JVMs JIT compiler is one of the fascinating mechanisms on the Java platform. It optimizes your code for performance, without giving away its readability. Not only that, beyond the “static” optimization methods of inlining, it also makes decisions based on the way that the code performs in practice.


1 Answers

As pointed out in the comments, it is difficult to tell without actually looking at the assembly. As yoy are using a REST-framework, I assume however that is would be hard to tell from the assembly as there is quite a lot of code to read.

Instead, I want to give you an educated guess because your code is an archetypical example of applying costant folding. When a value is inlined and not read from a field, the JVM can safely assume that this value is constant. When JIT compiling the method, the constant expression can therefore be safely merged with your framework code what probably leads to less JIT assebly and therefore improved performance. For a field value, even a final one, a constant value cannot be assumed as the field value can change. (As long as the field value is not a compile time constant, a primitive or a constant String, which are inlined by javac.) The JVM can therefore probably not constant fold the value.

You can read more on constant folding in the tutorial to the JMH where it is noted:

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.

I hope you used such a framework. Otherwise, you performance metric is unlikely to be valid.

From reading the byte code, you can generally not learn much about runtime performance as the JIT compiler can tweak the byte code to anything during optimization. The byte code layout should only matter when code is interpreted which is generally not the state where one would measure performance as performance-critical, hot code is always JIT compiled.

like image 85
Rafael Winterhalter Avatar answered Sep 22 '22 15:09

Rafael Winterhalter