My team and I are developing open source infrastructure solutions such as MantaRay, our open source JMS provider (yes, we are getting paid to write open source). One of my ongoing tasks is performance improvements. When you develop infrastructure you really need to think performance at all times.

Lately I was wondering if utilizing the new features of java 5.0 (AKA java 1.5) such as generics would improve my code’s performance. Generics looks like a type-safe solution, the theory behind it being that with generics you have an ArrayList that holds Integers or Strings and not an array of objects that needs to be cast to the specific concrete class. If you have the type information of the Object you are working with, then you do not need type checking, virtual method calls or and other operations that are required when using abstract objects.

Using java 1.4.2 I started to check this theory. I created two arrays, one consisting of Objects and the other of MyTestObject objects. I filled the two arrays with MyTestObject objects and then called the toString method on every element in the array. In order to make this clear, here is a small piece of the code:


// use object array
Object[] objectArray = new Object[1000];

for (int i = 0; i < objectArray.length; i++) {
    objectArray[i] = new MyTestObject(i);
}

for (int i = 0; i < objectArray.length; i++) {
    String result = objectArray[i].toString();
}

// use MyTestObject array
MyTestObject[] objectArray = new MyTestObject[1000];

for (int i = 0; i < objectArray.length; i++) {
    objectArray[i] = new MyTestObject(i);
}

for (int i = 0; i < objectArray.length; i++) {
    String  result = objectArray[i].toString();
}

There was a 10% improvement in performance using the MyTestObject-specific array. 10% improvement is a lot for me, so I verified the result by running the test thousands of times and got the same results. If generics are all they are cut to be then they will yield the same performance improvements.

Well, actually that is not the case; I have compiled this simple piece of code in java 5.0:


LinkedList<MyTestObject> list =
    new LinkedList<MyTestObject>();

list.add(new MyTestObject());
MyTestObject result = list.get(0);

Then I decompiled the code and got these results:


LinkedList list = new LinkedList();
list.add(new MyTestObject());
MyTestObject result =
    (MyTestObject)list.get(0);

A mystery! All of the type information has vanished. Later I found the answer on SUN’s site:
“Generics are implemented by type erasure: generic type information is present only at compile time, after which it is erased by the compiler…”

To make sure, I implemented my own LinkedList based on java 1.4.2 LinkedList; I just modified the internals to work with MyTestObject instead of object. My linked list showed better performance then java 5.0 LinkedList, although it was less then 10% it was still better, and I only provided runtime type information.

My conclusion is that the new generics feature is a step in the right direction, it looks like the template of C++ and provides type checking at compile time, it might even be more readable and easier to understand, but it fails to follow through and provide the type information needed at runtime to improve performance. The guys at Sun say that type erasure is needed to ensure backward compatibility. While backward compatibility is an important thing; improving the runtime performance is important too. I guess we need to find some way both can coexist.

Are Generics only syntactical sugaring?