Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The Hotspot JIT only inlines methods that are less than a certain (configurable) size. So using smaller methods allows more inlining, which is good.</p> <p>See the various inlining options on <a href="http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html" rel="noreferrer">this page</a>.</p> <hr> <p><strong>EDIT</strong></p> <p>To elaborate a little:</p> <ul> <li>if a method is small it will get inlined so there is little chance to get penalised for splitting the code in small methods.</li> <li>in some instances, splitting methods may result in more inlining.</li> </ul> <p><strong>Example</strong> (full code to have the same line numbers if you try it)</p> <pre><code>package javaapplication27; public class TestInline { private int count = 0; public static void main(String[] args) throws Exception { TestInline t = new TestInline(); int sum = 0; for (int i = 0; i &lt; 1000000; i++) { sum += t.m(); } System.out.println(sum); } public int m() { int i = count; if (i % 10 == 0) { i += 1; } else if (i % 10 == 1) { i += 2; } else if (i % 10 == 2) { i += 3; } i += count; i *= count; i++; return i; } } </code></pre> <p>When running this code with the following JVM flags: <code>-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:FreqInlineSize=50 -XX:MaxInlineSize=50 -XX:+PrintInlining</code> (yes I have used values that prove my case: <code>m</code> is too big but both the refactored <code>m</code> and <code>m2</code> are below the threshold - with other values you might get a different output).</p> <p>You will see that <code>m()</code> and <code>main()</code> get compiled, but <code>m()</code> does not get inlined:</p> <pre><code> 56 1 javaapplication27.TestInline::m (62 bytes) 57 1 % javaapplication27.TestInline::main @ 12 (53 bytes) @ 20 javaapplication27.TestInline::m (62 bytes) too big </code></pre> <p>You can also inspect the generated assembly to confirm that <code>m</code> is not inlined (I used these JVM flags: <code>-XX:+PrintAssembly -XX:PrintAssemblyOptions=intel</code>) - it will look like this:</p> <pre><code>0x0000000002780624: int3 ;*invokevirtual m ; - javaapplication27.TestInline::main@20 (line 10) </code></pre> <p>If you refactor the code like this (I have extracted the if/else in a separate method):</p> <pre><code>public int m() { int i = count; i = m2(i); i += count; i *= count; i++; return i; } public int m2(int i) { if (i % 10 == 0) { i += 1; } else if (i % 10 == 1) { i += 2; } else if (i % 10 == 2) { i += 3; } return i; } </code></pre> <p>You will see the following compilation actions:</p> <pre><code> 60 1 javaapplication27.TestInline::m (30 bytes) 60 2 javaapplication27.TestInline::m2 (40 bytes) @ 7 javaapplication27.TestInline::m2 (40 bytes) inline (hot) 63 1 % javaapplication27.TestInline::main @ 12 (53 bytes) @ 20 javaapplication27.TestInline::m (30 bytes) inline (hot) @ 7 javaapplication27.TestInline::m2 (40 bytes) inline (hot) </code></pre> <p>So <code>m2</code> gets inlined into <code>m</code>, which you would expect so we are back to the original scenario. But when <code>main</code> gets compiled, it actually inlines the whole thing. At the assembly level, it means you won't find any <code>invokevirtual</code> instructions any more. You will find lines like this:</p> <pre><code> 0x00000000026d0121: add ecx,edi ;*iinc ; - javaapplication27.TestInline::m2@7 (line 33) ; - javaapplication27.TestInline::m@7 (line 24) ; - javaapplication27.TestInline::main@20 (line 10) </code></pre> <p>where basically common instructions are "mutualised".</p> <p><strong>Conclusion</strong></p> <p>I am not saying that this example is representative but it seems to prove a few points:</p> <ul> <li>using smaller method improves readability in your code</li> <li>smaller methods will generally be inlined, so you will most likely not pay the cost of the extra method call (it will be performance neutral)</li> <li>using smaller methods <em>might</em> improve inlining globally in some circumstances, as shown by the example above</li> </ul> <p>And finally: if a portion of your code is really critical for performance that these considerations matter, you should examine the JIT output to fine tune your code and importantly profile before and after.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload