2009/02/07 SUN Java VM versus GNU Java Compiler

As you may know, Java is (after compilation) still an interpreted language. E.g. the output of the SUN Java compiler is a byte-code which is not native to the processor of your computer so it needs to be translated at run-time (when you invoke the program) each time it is invoked. Now the SUN Java JRE (the program which does the runtime interpreting) is very clever and very efficient so I wondered: why would I use the GNU Java Compiler? The GNU Java compiler takes your Java sources (or .class-files or even a .jar-file) and compiles it to a native binary, something the processor of your computer understands. Why would I use that one since it defeats the purpose of Java; to be able to make your program run everywhere. I thought; maybe it helps the speed a little?
For this test I wrote this simple (and pretty dumb - there's plenty room for optimalisations who would affect both the Java version as well as the binary version so not relevant to this test) mandelbrot fractal implementation:
class jst
{
        public static void main(String [] args)
        {
                int xres = 4096, yres = 4096;
                double x1 = -2.0, x2 = 2.0;
                double y1 = -2.0, y2 = 2.0;
                int it = 255, dummy = 0;

                for(int y=0; y<yres; y++)
                {
                        if ((y % 100) == 0)
                        {
                                System.out.println("left: " + (yres - y));
                        }

                        for(int x=0; x<xres; x++)
                        {
                                double xc = x1 + (x2 - x1) * ((double)x / (double)xres);
                                double yc = y1 + (y2 - y1) * ((double)y / (double)yres);
                                double X = 0.0, Y = 0.0;
                                int curIt = 0;

                                do
                                {
                                        double temp = Math.pow(X, 2.0) - Math.pow(Y, 2.0) + xc;
                                        Y = 2.0 * X * Y + yc;
                                        X = temp;

                                        curIt++;
                                }
                                while((Math.pow(X, 2.0) + Math.pow(Y, 2.0)) < 4.0 && curIt < it);

                                if (curIt == it)
                                {
                                        dummy++;
                                }
                        }
                }

                System.out.println("result: " + dummy);
        }
}
I compiled it for the SUN Java JRE (using Java compiler version 1.6.0_07, Debian package):
folkert@belle:~/Personal/src/javaspeedtest$ javac jst.java
and with the GNU Java compiler (4.3.2-2, Debian package):
folkert@belle:~/Personal/src/javaspeedtest$ gcj --main=jst -o jst -march=nocona -O2 -m64 -fomit-frame-pointer jst.java
And then I ran both programs two times. The results are staggering: the binaries are
more than 13 times faster!

Java
run 1: 0m54.620s
run 2: 0m54.560s
Binary
run 1: 0m4.210s
run 2: 0m4.260s


Please note: you won't see this enormous performance with all workloads. E.g. a file-i/o bound program will probably show no difference.






feedback