Affects Version/s: 1.3.3
Fix Version/s: 2.0.0
Environment:Mac OS X 10.6.2, Java 6
Number of attachments :
During some recent profiling of our application, the profiler (jprofiler) put several bitronix functions at the top of it's "hotspot" list. Not that these functions were particularly inefficient, but because they are called millions of times they end up consuming more resources than you might imagine.
A couple of tweaks to these (two) classes resulted in them disappearing completely from the "hotspot" list. The two classes in question are Uid.java and Encoder.java. I have attached them here.
Just a few comments on the (overall minor) changes:
Basically unrolled some (most) of the loops. Old trick, very effective. Hotspot compiler doesn't seem smart enough to unroll these itself. Probably 5-10x faster, no loop comparator or incrementer involved. Either way, they disappeared from the jprofiler radar as these tweaks.
This class is used A LOT, therefore I gave it a workover. Notes:
equals() - removed the use of "instanceof", it's slow. In 99% (or 100%) of the cases you are comparing apples-to-apples, better to just catch the ClassCastException if it happens and return false.
arrayHashCode() - the hash algorithm was not good. It used a loop that basically did: total += uid[i]. This means that for an 8-byte UID (theoretically a 64-bit number with a range of trillions) the maximum achievable hash was 8*256 = 2048. Granted ultimately the hash is an int, which is 32-bit, but still the range is +/-2 billion. The new code implements a "classic" oldie but goodie hash. Simple, reasonably dispersed over the range of int (few hash collisions), and fast.
arrayToString() - since arrayToString() and arrayHashCode() are both called in the Uid constructor, their performance is important. The new arrayToString() avoids StringBuilder.append() entirely and employs a lookup table of only 16 values. By using a char array and avoiding method invocation overhead, this method is many MANY times faster than the previous.