Showing posts from 2010

More uses for dynamic code in Java.

In 2008 I wrote a library for compiling and running dynamic code in Java. Essence JCF At the time the purpose was to load configuration files which were written in Java rather than XML or properites files. One advantage this library has is that it can load into the current class loader, rather than requiring an additonal class loader so the interface or class can be used immediately in code without the need for reflection. See below for an example. For me, it has been a very cool solution without a unique problem to solve. i.e. there wasn't a problem it solved particularly well. Since then, I have come across a few situations where it is particularly useful. Objects in direct memory Using dynamically generated code, you can build a data store from an interface which is row based or column based, stored either in the heap or in direct memory. Both can reduce the number of objects created improving cache locality and reducing GC times. Precompile expressions Expressions which are

Two uses for enum most people forget.

The enum can be used to create enumerated values and even many instances with different implementations but there are two simple uses which are appear to be under utilised. The utility class A utility class is a class with no instances. To declare this as an enum is trivial. You just give it no instances. public enum MyUtils {; public static String process(String text) { /* ... */ } } The singleton A singleton which is a class which has one and only one instances, ideally loaded lazily. Using the lazy loading of classes can give the same benifit in a simpler/thread safe way. To declare a singleton as an enum, you give it one instance and only reference the instance rather than the class. public enum Singleton implements SingletonService { INSTANCE; public String instanceMethod(String text) { /* ... */ } } An enum can implement an interface, allowing it to be mocked out where ever the interface has been used.

Gotcha: Save on objects and get more Full GCs.

We have system which is latency sensive and object light. However as we tuned the system to run less minor collections we saw the number of Full GCs increase. Some investigation found that there is a timer for RMI which checks if a GC has occurred in the last hour and if it hasn't performs a Full GC. :P If you are not really using RMI, this is undesireable. There are two command line options which can be increased to reduce the number of these only-for-RMI Full GCs. Increasing just one has no effect. The defaults are: -Dsun.rmi.dgc.server.gcInterval=3600000 -Dsun.rmi.dgc.client.gcInterval=3600000 For more details bug id 6200091 See line 109 of The sun.misc.GC.Daemon class

Java NIO is faster than Java IO for Sockets

Most benchmarks comparing Java IO Sockets and Java NIO SocketChannel, compare these libraries using different threading models. Typcially this is Java IO using dedicated thread(s) for each Socket compared with the a dispatcher model for Java NIO, with non-blocking SocketChannels sharing threads. However, this comparison is using IO and NIO using the same threading model with one decidiated thread per Socket/SocketChannel. The point of this comparision is to say, NIO doesn't have to be slow, its just that threading model which is commonly used with NIO is perhaps more trouble than its worth. For more details, including the source see my wiki page on this topic.

Stupidly long class name or a geeky poem?

In the JRE is a stupidly long class name, only a code generator could produce such a long name. (Which the developer of the code generator never checked I assume) InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState Or is it a geeky poem burried in the code? InternalFrame InternalFrame Title Pane, Internal Frame Title Pane. Maximize Button Window, Not Focused State. The moral of the story, always check the readability/sanity of generated code.

Memory is cheaper than you think.

Many developers spend time trying to save memory without much thought about how much their time is worth and how much the memory is worth. The occasional Java forum question about how to save a few MB of memory, fails to consider how much money that memory is worth. I have compiled a list of machines sold by a major vendor, by memory in them and included the list price for them. These systems support Windows, Lunix and Java. I have made the assumption that machines wth more memory need more processing power, indicated by the GHz and are only included as they have a baring on the price. In the last column you can see that the cost is about £80 per GB. Given a typical developer costs over £40/h, this suggests it is worh spending about 2 hours to save 1 GB. Sometimes it is worth spending time saving memory. However, how much time is 1 MB worth? About 7 seconds. This is significant because I often otimise my code to save a lot less than 1 MB and I spend more than 7 seconds doing it (in

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

Locking a ConcurrenthashMap for exclusive access.

A friend recently pointed me to an acticle on ConcurrentHashMap which indicated to him that you can't lock a ConcurrentHashMap for exclusive access. This came as a surprise to me as I have been doing just that for years. Hashtable and Collections.synchronizedMap achieve thread safety by synchronizing every method. This means that when one thread is executing one of the Map methods, other threads cannot until the first thread is finished, regardless of what they want to do with the Map. In most cases, ConcurrentHashMap is a drop-in replacement for Hashtable or Collections.synchronizedMap(new HashMap()). However, there is one significant difference -- synchronizing on a ConcurrentHashMap instance does not lock the map for exclusive use. In fact, there is no way to lock a ConcurrentHashMap for exclusive use -- it is designed to be accessed concurrently. This appears confused to me. On the one hand it state