Posts

Showing posts from June, 2010

Fastest way to lock/synchronize objects.

Overview There have been some comparison of Lock vs synchronization in Java. I wanted to compare the latest version of Java with using a plain AtomicLong and AtomicReference as an alternative to locking. Summary The results are much the same for Java 5.0 and later, provided your JIT has optimised the code. I found this required the methods to be called between 10K and 50K times to get the best optmisation (depending on the approach used) In short, the fastest way to perform lock/synchronization is to make sure your JVM is warmed up first. Results The tests were single threaded and run on a 3 GHz Xeon processor running SLES 11. Timings are in nano-seconds, that is one billionth of a second. For Java 1.4.2 I used the backport v2.1 Version bits concurrent Lock synchronized AtomicLong AtomicReference 1.4.2 u 18 32 130 40 115 105 5.0 u 22 64 23 15 15 16 6 u 7 64 21 20 14 15 6 u 20 32 23 20 19 12 6 u 20 64 16 20 12

OMG: Using a triple cast.

I have used double casts before but today found myself writing a triple cast. :P The situation was; I need a method which returned the default value for a type. public static <T> T nullValue(Class<T> clazz) { if (clazz == byte.class) return (T) (Byte) (byte) 0; // other primitive types handled. return null; } Certainly this is casting madness. So I wrote the method a different way. static { NULL_MAP.put(byte.class, (byte) 0); // other primitive types handled. } public static <T> T nullValue(Class<T> clazz) { return (T) NULL_MAP.get(clazz); } There the same casting is going on, but one cast is implied and the other two are seperated. Its not as ugly and more efficient. :)

Calculating an average.

A long standing bug in many algorithims is using the obvious int m = (h + l)/2; The problem with this is that (h + l) can overflow for large values of h and l. One alternative is a cumbersome int m = l + (h - l)/2; Or the one I prefer is using >>> to perform an unsigned divide by two int m = (h + l) >>> 1; For example, say m, h and l where bytes and h = 100 and l = 90. In the first case, h + l is -65 due to the overflow, so m = -32. (incorrect) In the second case, h - l is 10, so m = 95 (correct) In the last case, h + l is -65 or 10111110 in binary. Unsigned shifting right by 1 is 1011111 or 95. (correct)

Monotonically increasing time

Overview There are times you need to have a simple monotonicly increasing clock for timestamps but one which doesn't drift too far from the system time. Simple increasing clock This clock is close to the system time, provided it is classed less than 1000 times per second. public enum Time {; private static long lastTime; public synchronized static long increasingTimeMillis() { long now = System.currentTimeMillis(); if (now > lastTime) return lastTime = now; return ++lastTime; } } A more complex timer avoids the overhead of synchronization. public enum Time {; private static final AtomicLong lastTime = new AtomicLong(); public static long increasingTimeMillis() { long now = System.currentTimeMillis(); long time = lastTime.getAndIncrement(); if (now > time) { lastTime.compareAndSet(time+ 1 , now); return lastTime.getAndIncrement(); } return time; } }

Accuracy of double representation for decimals.

Overview There is some debate as to whether BigDecimal or double is best for monetary values. The simplest answer is, if in doubt choise BigDecimal as it is seen as the safer option. When doubles are used, the common approach is the round the result before displaying. However, how large can the value be before rounding results in an error? Approach I have written a program to find the largest error you get for a decimal with two decimal places for numbers above and below powers of two. The reason powers of two are used is each larger power uses more bits, thus less bits for the decimal representation (increasing the error) The rounding error which is too large is one which would round incorrectly. In the case of two decimal places, a rounding error of 0.005 or more would result in an error even with rounding. Searching for the largest rounding error In this program, I have constructed a number with two decimal places using a double and a String for comparison and used BigDecimal for ac