Posts

Showing posts from May, 2011

When the JIT gets it wrong

Overview I have often wondered what you would see if the JIT compiled code incorrectly, but it has been a long time since I found an example. A not so infinite loop There are many way to write an infinite loop. One confusing way is to write for(int i=0; i &lt= Integer.MAX_VALUE; i++) This is an infinite loop because i as an int value is always less than or equal to the maximum value, by definition. The JIT can detect this and take action. However the action taken in Oracle Java 6 update 25 is surprising. It just stops the loop, first at a rather random point and later after one iteration. public static void main(String[] args) { for(int i=0;i<10;i++) generate(Integer.MAX_VALUE); for(int i=0;i<10;i++) generate2(Integer.MAX_VALUE); System.out.println("End of Main"); } // generate primes. public static void generate(int limit) { int lastPrime = 0; for (int i = 3; i <= limit; i += 2) if (isPrime(i))

Forgotten feature of LinkedHashMap.

Overview LinkedHashMap has a couple of nice features. To me the most under-utilised feature as a simple cache with FIFO or LRU eviction policy. LRU Cache A cache which evicts the Least-Recently-Used entry is useful for efficiently caching the most used entries. Map<Key, Value> cache = new LinkedHashMap<Key, Value>(16, 0.7f, true) { private static final int MAX_ENTRIES = 100; protected boolean removeEldestEntry(Map.Entry<Key, Value> eldest) { return size() > MAX_ENTRIES; } }; This use of the constructor tell the LHM to order entries by last access. FIFO cache An alternative is to evict the oldest entries. Map<Key, Value> cache = new LinkedHashMap<Key, Value>() { private static final int MAX_ENTRIES = 100; protected boolean removeEldestEntry(Map.Entry<Key, Value> eldest) { return size() > MAX_ENTRIES; } }; The default behaviour of the LHM to order entries in the order added.

How to get C like performance in Java

Overview Java has many areas which can be slow. However for every problem there is a solution. Many solutions/hacks require working around Java's protections but if you need low level performance it is still possible. Java makes high level programming simpler and easier at the cost of making low level programming much harder. Fortunately most applications follow the rule of thumb that you spend 90% of your time in 10% of the code. This implies you are better off 90% of the time, worse off 10% of the time. ;) It makes me wonder why you would write more than 10% of your code in C/C++ for most projects. There will be some projects where C/C++ is the only sensible solution, but I suspect most C/C++ projects would more productive with the use of higher level languages like Java. One way to get C-like performance is to use C via JNI for key sections of code. If you want to avoid using C or JNI there are still ways you can get the performance you want. Note: Most of these sugg

Special non-exceptions.

Overview There are a couple of Throwables which have surprising properties. Throwable can be extended When extending Throwable it is checked by the compiler, through is not an Exception. public static void main(String... args) throws MyThrowable { throw new MyThrowable(); // will not compile unless MyThrowable is handled. } class MyThrowable extends Throwable { } This prints out the MyThrowable with a stack trace as expected. The slient Error A throwable which extends ThreadDeath is silent as it is deadly. ;) public static void main(String... args) { throw new MyThrowable(); } class MyThrowable extends ThreadDeath { } When this runs, no error/exception is printed, the thread just exits. This is because the error/exception is printed by ThreadGroup.uncaughtException() which ignores instanceof ThreadDeath by default. The ThreadDeath error is used by Thread.stop() and although this method is deprecated, the ThreadDeath error is not deprecated and even describes itself

StringBuffer is dead, long live StringBuffer

Overview StringBuilder was introduced seven years ago as a replacement for StringBuffer where you didn't need thread safety. From the Javadoc for StringBuilder This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations. StringBuffer is dead? So you might believe that StringBuffer is basically dead because it has very few uses which cannot be replaced by StringBuilder and those are neatly wrapped by classes like StringWriter. However, if the JDK is anything to go by, having a drop in replacement is just not enough to get people to migrate existing code. Class Uses in the Java 6 update 25 src.zip StringBuffer    1,409 StringBuilder    

What can make Java code go faster and slower.

Overview Something is fairly widely known is that the JVM optimises code as it runs.  This can result in code running much faster as you execute it many times. However, something not so well understood is what you do before a section of code can slow it down. Warming up code int[] display = {0, 1, 10, 100, 1000, 10000, 20000, 100001}; for (int i = 0; i <= display[display.length - 1]; i++) { long start = System.nanoTime(); doTask(); long time = System.nanoTime() - start; if (Arrays.binarySearch(display, i) >= 0) System.out.printf("%,d: Took %,d us to serialize/deserialze " + "GregorianCalendar%n", i, time / 1000); } outputs 0: Took 34,751 us to serialize/deserialze GregorianCalendar 1: Took 1,551 us to serialize/deserialze GregorianCalendar 10: Took 1,474 us to serialize/deserialze GregorianCalendar 100: Took 1,010 us to serialize/deserialze GregorianCalendar 1,000: Took 264 us to serialize/deserialze Grego