Monday, October 3, 2011

Are static blocks interpreted ?


Are static block interpreted or does the JIT play a part?

When are methods optimized?

A method will be optimized when it is called often enough. This is controlled by the -XX:CompileThreshold=10000 flag. The compilation occurs in the background by default and a short time later, the optimized version of the code will be used. (This is why it doesn’t always happen at exact the 10K mark)

However, loops can also be optimized if they are called often enough. This typically takes about 2-5 seconds. This is why any bound loop which does nothing takes about 2-5 seconds. (This is how long it takes the JIT to realize the loop doesn’t do anything)

How does this apply to static blocks?

Static block are never called more than once. Even if they are loaded by different class loaders, they are optimized independently. (In the unlikely event you loaded the same class 10,000 times, it still wouldn't be optimized)

However, it is quite possible to have a loop iterate many times in a static block (though rare) this can result in the static block begin optimized by the JIT.

public class Main {
    static {
        long start = System.nanoTime();
        for (int i = 0; i < 5000; i++) ;
        long time = System.nanoTime() - start;
        System.out.printf("Took %.3f ms to iterate 5 thousand times%n", time / 1e6);

        long start1 = System.nanoTime();
        for (int i = 0; i < 5000; i++) ;
        long time1 = System.nanoTime() - start1;
        System.out.printf("Took %.3f ms to iterate 5 thousand times%n", time1 / 1e6);

        long start2 = System.nanoTime();
        for (int j = 0; j < 1000 * 1000; j++)
            for (int i = 0; i < 1000 * 1000; i++) ;
        long time2 = System.nanoTime() - start2;
        System.out.printf("Took %.3f ms to iterate 1 trillion times%n", time2 / 1e6);

        long start3 = System.nanoTime();
        for (int j = 0; j < 1000 * 1000; j++)
            for (int i = 0; i < 1000 * 1000; i++) ;
        long time3 = System.nanoTime() - start3;
        System.out.printf("Took %.3f ms to iterate 1 trillion times%n", time3 / 1e6);
    }

    public static void main(String[] args) {
    }
}

run it with -XX:+PrintCompilation flag outputs.

64   1       java.lang.String::charAt (33 bytes)
     75   2       java.lang.String::hashCode (64 bytes)
Took 0.067 ms to iterate 5 thousand times
Took 0.062 ms to iterate 5 thousand times
     88   1%      Main:: @ 124 (249 bytes)
Took 4.860 ms to iterate 1 trillion times
Took 0.001 ms to iterate 1 trillion times


You can see that a loop of 5,000 is not enough to trigger optimization, but a much larger loop does trigger optimization. Without the JIT, there is no way the loop of one trillion times would finish in 3 seconds.

Once the method has been optimize the last one trillion loop takes practically no time at all.

Why thread priority rarely matters


It is tempting to use the Thread.setPriority() option in Java. However for many applications this is more a comment for the developer than something which will make a measurable difference. esp. with multi-core systems. 

If you have plenty of free CPU, every thread which can run will run. The OS has no reason not to run a low priority thread or process when it has free resources. 

If your system is close to 100% of CPU on every core, the OS has to make a choice as to how much time each thread or process gets on the CPU and it is likely to give favor to higher priority threads over lower priority threads, (many operating systems ignore the hint) and other factors are likely to matter as well. 

This priority only extends to raw CPU. Threads compete equally for CPU cache, heap space, CPU to memory bandwidth, file cache, disk IO, network IO and everything else. If any of these resource are in competition, they are all equal. 

To set a high priority on Windows you need to be an administrator and on Linux you need to be root to set the priority of a thread. Different Implementations and operating systems can ignore this hint. 

If your application is heavily CPU bound, using every core, not using any other system resources significantly like IO or memory and your OS doesn't ignore the hint, the thread priority might make a difference.

If in doubt, I wouldn't bother setting it because someone might think it does something.

How To Write Directly to a Memory Locations In Java


If anyone has ever told you, you cannot write directly to memory locations in java, then they are wrong. Well, to be precise, they are half-wrong, you can write to memory locations as long as the memory is control by the JVM.

Although this is possible, I strongly recommend that you don’t do it. Failing to get your code 100% correct will cause the JVM to crash. There maybe cases where you wish to optimize you code and write to memory directly but I would only do this as a last resort.

On the Hotspot JVM, you are able to write and read directly to memory. One of the advantages of this technique is that is very fast, however it comes with no safe guards usually provided by the Java APIs. Its also not document by SUN.
Use the java class sun.misc.Unsafe, some of the methods you may be interested in are :

public native long getAddress(long address);
public native void putAddress(long address, long value);
public native long allocateMemory(long size);
public native long reallocateMemory(long l, long l1);
public native void setMemory(long l, long l1, byte b);
public native void copyMemory(long l, long l1, long l2);

You can't instantiate the class directly as it has a private constructor, so you will have to create an instance like this:

try {
   Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
   field.setAccessible(true);
   unsafe = (sun.misc.Unsafe) field.get(null);
} catch (Exception e) {
   throw new AssertionError(e);
}


you can then call

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class Direct {

    public static void main(String... args) {
        Unsafe unsafe = null;

        try {
            Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (sun.misc.Unsafe) field.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }

        long value = 12345;
        byte size = 1;
        long allocateMemory = unsafe.allocateMemory(size);
        unsafe.putAddress(allocateMemory, value);
        long readValue = unsafe.getAddress(allocateMemory);
        System.out.println("read value : " + readValue);

    }
}


this will output :
read value : 12345

Performance Of Arraylist compared to Array


The performance will very much depend on the VM involved, and a variety of other considerations.

The ArrayList is backed by an array, when storing data into the ArrayList, more work is performed, for example:
  1. A nullity check (to see whether the ArrayList reference is non-null).
  2. A bounds check — to handle the resizing logic, to resize the array that backs its. This array is resized in chunks.
    so the size of the list is usually smaller than the length of the array.
  3. Potentially a virtual method indirection, depending on whether the JIT has managed to inline the call.
  4. Its worth noting that usually the performance of one single method call doesn't matter much, usually its not worth sacrificing good design for few micro-seconds. Only optimize your fast paths, its likely most of your code will be run infrequently.