Today in class we went over the final keyword again and some method inlining scenarios. I was curious if the java compiler(javac 1.6.0_26) was able to do inlining. Turns out it does and it does it better than expected. We went over 4 scenarios for inlining in Java:
- The class is final
- The method is final
- The method is private
- Method is static
We also went over when Java cannot inline methods:
- Dynamic loading
- The method is too complicated(the method contains a loop).
Turns out if the method is “simple enough”, dynamic loading isn’t even a problem. I say “simple enough” because the methods I am testing only return constant values. I do not have them do any manipulation of data or pass in any arguments to the methods.
I tested (1), (2), and (4) from above. I didn’t bother with (3) because it didn’t really fit how I tested each case(plus I figured the idea came across with the other 3). Each test consists of Java objects and a test file. I have a test file for each case to make sure that a run a fresh JVM on each run for fairness purposes(don’t want anything cached in the JVM or have the garbage collector run when I don’t want it too). I also do a warm up loop at the start of the JVM(this is common when doing testing numbers). This flushes out whatever may be in the cache as well as get the system moving. I ran each test from 0 to Integer.MAX_VALUE and the time returned is in milliseconds which I attained using System.currentTimeMillis(), but you can read the code to get more details on how it was implemented. Here are the numbers:
Reference Test
-------------
Duration=5ms
Class final test
----------------
Duration=6ms
Static test
-----------
Duration=5ms
Method final test
-----------------
Duration=6ms
Dynamic loading test
--------------------
Duration=5ms
Loop inline test
----------------
Duration=176ms
The reference test is just calling a method that is neither static nor final and the class is not final either. This is how most methods in Java are written to be. As you can see the reference test is about the same time as the other “optimized” tests. This is because the JVM can see that this method can also be inlined because it is “simple enough”. This “simple enough” also explains the dynamic loading. More extensive tests need to be done to gain full insight of how sophisticated the java compiler is in terms of optimizations but this is the starting point. However, an example of when the java compiler cannot do method inlining is when the method has a loop.
All tests were run on a 64bit UTCS server(hasselblad.cs.utexas.edu). The source files can be downloaded with the command:
- git clone git://github.com/jonmon89/Java_Performance.git
Running ‘make run’ after downloading the files will compile and run each test(The makefile isn’t my best work but it worked for these tests).
A quick article about Java’s method inlining is here: