2009-02-16

Java is faster than native


There is a myth that native is much faster than java. Lots of frameworks speculate this myth and using lots of native methods from java. But how often they are implementing same functionality and check native against true-java? They are often diving so deep in own fantasies about native performance that it is almost religion, they just don't accept facts. But how much it takes to JVM to invoke method from native library? And how much is it comparing to raw java interpretation?

I don't like to use things that I don't understand. Almost all methods from Math class is native, and I can't see sources of that classes. There are some functions that would be hard to implement, like Math.sin() or Math.cos(), but there are some easy-to-implement methods. This time I need functionality of method Math.pow(). It is not hard to implement it in java:

private double pow(double value, double pow) {
  double result = value;
  for (int i = 1; i < pow; i++) {
    result = result * value;
  }
  return result;
}

And it is not hard to implement some raw test using case from current developed application:

private static final int times = 1000000;
public static void main(String[] args) {
  // running test 10 times to "hotspot" it
  for (int i = 0; i < 10; i++) {
    // I know, I know, you can never
    // preallocate long, but I like it:
    long start = 0;
    long end = 0;
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("pow: " + (end - start));
    // cleaning JVM every time before next cycle:
    System.gc();
    System.runFinalization();
    System.gc();
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      Math.pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("math: " + (end - start));
    System.gc();
    System.runFinalization();
    System.gc();
    // and running once more to be sure in hotspot:
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("pow: " + (end - start));
    System.gc();
    System.runFinalization();
    System.gc();
    start = System.currentTimeMillis();
    for (int j = 0; j < times; j++) {
      Math.pow(10, 10);
    }
    end = System.currentTimeMillis();
    System.out.println("math: " + (end - start));
    System.gc();
    System.runFinalization();
    System.gc();
  }
}


I just wanted to figure out how slow is my implementation, but results were totally unexpected!

run-single:
pow: 63
math: 797
pow: 78
math: 797
pow: 78
math: 781
pow: 78
math: 781
pow: 63
math: 781
pow: 63
math: 781
pow: 63
math: 797
pow: 63
math: 797
pow: 63
math: 797
pow: 63
math: 782

It's 10 times faster than Math.pow() when raising power of 10!!

Think different. Think faster!

No comments: