Posts

Accessing Chronicle Engine via NFS

Overview Chronicle Engine is a data virtualisation layer.  It abstracts away the complexity of accessing, manipulating and subscribing to various data source so that the user of that data doesn't need to know how or where  the data is actually stored.  This means that this data can be migrated between systems or stored in a manner which is more efficient but would be to complex for the developer to use. The basic interfaces are Concurrent Map and a simple Pub/Sub.  Using these in combination with the stream like filters and transformation you can access files, in memory data caches, LDAP, SQL Databases, Key-value NoSQL databases and low latency persisted stores. What we are investigating is using NFS as a means of access as well as our Java and C# client to access the data in a natural way.  This way any program on Windows, Unix or MacOSX could use it. How might this look? Access via NFS. The data stores in Chronicle Engine are organise hierarchically ...

Is using Unsafe really about speed or functionality?

Overview Around 6 years ago, I started using a class which up to that point was just a curiosity sun.misc.Unsafe .  I had used it for deserialization and re-throwing Exceptions but not used all it's capabilities or talked about it publicly. The first open source library I saw which did use Unsafe in a serious way was Disruptor. This encouraged me that it could be used in a stable library.  About a year later I released my first open source libraries, SharedHashMap (later Chronicle Map) and Chronicle (later Chronicle Queue).  This used Unsafe to access off heap memory in Java 6.  This made a real difference to the performance of off heap memory, but more importantly what I could do with shared memory. i.e. data structures shared across JVMs. But how much difference does it make today? Is using Unsafe always faster? What we are look for is compelling performance differences.  If the difference is not compelling, using the simplest code possible makes more ...

Using JMH to find the fastest way to encode/decode UTF8

Overview I had played with JMH before however this is the first time I have used JMH to solve a production problem.  I had some idea how to optimise the code involved but trying different combinations with JMH lead to a significant improvement. In this test I am encoding a String as UTF8 to direct memory so it can be written to a TCP socket.  Also I need to take data written to direct memory via an NIO SocketChannel.read and encode it into a StringBuilder (which can be reused) The tests These tests involved a combination of using reflection to obtain the underlying data structure of String and StringBuilder but also using Unsafe to access the native memory. To my surprise, access String via reflection appeared to be no faster, possibly slower. However @jponge pointed out that I needed to be returning a result from each benchamrk to avoid dead code elimination.  After I did this, the access via reflection was faster. See encode_unsafeLoopCharA t ...

How and Why to Serialialize Lambdas

Overview Serializing lambdas can be useful in a number of use cases such as persisting configuration, or as a visitor pattern to remote resources. Remote Visitors For example, so I want to access a resource on a remote Map, I can use get/put, but say I just want to return a field from the value of a Map, I can pass a lambda as a visitor to extract the information I want. MapView userMap =      Chassis. acquireMap ( "users" , String. class , UserInfo. class ); userMap.put( "userid" , new UserInfo( "User's Name" )); // print out changes userInfo.registerSubscriber(System. out ::println); // obtain just the fullName without downloading the whole object String name= userMap.applyToKey( "userid" , u -> u. fullName ); // increment a counter atomically and trigger // an updated event printed with the subscriber. userMap.asyncUpdateKey( "userid" , ui -> {      ui. usageCounter ++;      return ui; }); // increm...

Puzzler: nested computeIfAbsent

Overview The Java 8 libraries have a new method on map, computeIfAbsent.  This is very useful way to turn your Map into a cache of objects associated with a key. However, there is a combination you might not have considered; what happens if you call computeIfAbsent inside itself. map.computeIfAbsent(Key. Hello , s -> { map.computeIfAbsent(Key. Hello , t -> 1 ); return 2 ; }); enum Key { Hello } While this might seem like a strange thing to do in simple cases, in more complex code you could do this by accident (as I did this afternoon)  So what happens?  Well it depends on the collection you are using. HashMap: {Hello=2} WeakHashMap: {Hello=2} TreeMap: {Hello=2} IdentityHashMap: {Hello=2} EnumMap: {Hello=2} Hashtable: {Hello=2, Hello=1} LinkedHashMap: {Hello=1, Hello=2} ConcurrentSkipListMap: {Hello=1} ConcurrentHashMap:  Note: ConcurrentHashMap never returns.  It's locking doesn't appear to be re-entrant. Co...

What are the bad features of Java.

Overview When you first learn to develop you see overly broad statements about different features to be bad, for design, performance, clarity, maintainability, it feels like a hack, or they just don't like it. This might be backed by real world experience where removing the use of the feature improved the code.  Sometimes this is because the developers didn't know how to use the feature correctly, or the feature is inherently error prone (depending whether you like it or not) It is disconcerting when either fashion, or your team changes and this feature becomes fine or even a preferred methodology. In this post, I look at some of the feature people like to hate and why I think that used correctly, they should be a force for good.  Features are not as yes/no, good/bad as many like to believe. Checked Exceptions I am often surprised at the degree that developers don't like to think about error handling.  New developers don't even like to read error messages. I...

Inconsistent operation widen rules in Java

Overview When you perform a unary or binary operation in Java the standard behaviour is to use the widest operand (or a wider one for byte, short and char).  This is simple to understand but can be confusing if you consider what the optimal type is likely to be. Multiplication When you perform multiplication, you often get a much large number than either of the individual numbers in magnitude. i.e. |a*b| >> |a| and |a*b| >> |b| is often the case.  And for small types this works as expected Consider this program public static void main(String[] args) throws IOException {     System.out.println(is(Byte.MAX_VALUE * Byte.MAX_VALUE));     System.out.println(is(Short.MAX_VALUE * Short.MAX_VALUE));     System.out.println(is(Character.MAX_VALUE * Character.MAX_VALUE));     System.out.println(is(Integer.MAX_VALUE * Integer.MAX_VALUE));     System.out.println(is(Long.MAX_VALUE * Long.MAX_VALUE)); } static Str...