Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Large difference in speed of equivalent static and non static methods

In this code when I create an Object in the main method and then call that objects method: ff.twentyDivCount(i)(runs in 16010 ms) , it runs much faster than calling it using this annotation: twentyDivCount(i)(runs in 59516 ms). Of course, when I run it without creating an object, I make the method static, so it can be called in the main.

public class ProblemFive {      // Counts the number of numbers that the entry is evenly divisible by, as max is 20     int twentyDivCount(int a) {    // Change to static int.... when using it directly         int count = 0;         for (int i = 1; i<21; i++) {              if (a % i == 0) {                 count++;             }         }         return count;     }      public static void main(String[] args) {         long startT = System.currentTimeMillis();;         int start = 500000000;         int result = start;          ProblemFive ff = new ProblemFive();          for (int i = start; i > 0; i--) {              int temp = ff.twentyDivCount(i); // Faster way                        // twentyDivCount(i) - slower              if (temp == 20) {                 result = i;                 System.out.println(result);             }         }          System.out.println(result);          long end = System.currentTimeMillis();;         System.out.println((end - startT) + " ms");     } } 

EDIT: So far it seems that different machines produce different results, but using JRE 1.8.* is where the original result seems to be consistently reproduced.

like image 843
Stabbz Avatar asked May 26 '15 09:05

Stabbz


People also ask

What's the difference between a static method and a non static method?

A static method can access only static members and can not access non-static members. A non-static method can access both static as well as non-static members. Static method uses complie time binding or early binding. Non-static method uses run time binding or dynamic binding.

Which one is faster static method or instance method?

Static methods are faster but less OOP.

Do static methods run faster?

They are faster — Static methods are slightly faster than instance methods because in instance methods, you are also working with an implicit this parameter. Eliminating that parameter gives a slight performance boost in most programming languages.

Are static methods faster Java?

As expected, virtual method calls are the slowest, non-virtual method calls are faster, and static method calls are even faster.


2 Answers

Using JRE 1.8.0_45 I get similar results.

Investigation:

  1. running java with the -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining VM options shows that both methods get compiled and inlined
  2. Looking at the generated assembly for the methods themselves shows no significant difference
  3. Once they get inlined, however, the generated assembly within main is very different, with the instance method being more aggressively optimised, especially in terms of loop unrolling

I then ran your test again but with different loop unrolling settings to confirm the suspicion above. I ran your code with:

  • -XX:LoopUnrollLimit=0 and both methods run slowly (similar to the static method with the default options).
  • -XX:LoopUnrollLimit=100 and both methods run fast (similar to the instance method with the default options).

As a conclusion it seems that, with the default settings, the JIT of hotspot 1.8.0_45 is not able to unroll the loop when the method is static (although I'm not sure why it behaves that way). Other JVMs may yield different results.

like image 67
assylias Avatar answered Sep 19 '22 05:09

assylias


Just an unproved guess based an assylias' answer.

The JVM uses a threshold for loop unrolling, which is something like 70. For whatever reason, the static call is slightly bigger and doesn't get unrolled.

Update results

  • With the LoopUnrollLimit in the below 52, both versions are slow.
  • Between 52 and 71, only the static version is slow.
  • Above 71, both versions are fast.

This is strange as my guess was that the static call is just slightly bigger in the internal representation and the OP hit a strange case. But the difference seems to be about 20, which makes no sense.

 

-XX:LoopUnrollLimit=51 5400 ms NON_STATIC 5310 ms STATIC -XX:LoopUnrollLimit=52 1456 ms NON_STATIC 5305 ms STATIC -XX:LoopUnrollLimit=71 1459 ms NON_STATIC 5309 ms STATIC -XX:LoopUnrollLimit=72 1457 ms NON_STATIC 1488 ms STATIC 

For those willing to experiment, my version may be useful.

like image 37
maaartinus Avatar answered Sep 19 '22 05:09

maaartinus