I stumbled upon a bizarre performance issue related to the StringBuilder's append method. I noticed what appeared to be a foolish mistake - string concatenation during the use of the StringBuilder constructor (this even shows up as a warning in the NetBeans IDE).
Version 1
int hash = -1; //lazily computed, also present in Version 2
int blockID = ... //0 to 1000, also present in Version 2
int threadID = ... //0 to 1000, also present in Version 2
boolean hashed = false; //also present in Version 2
@Override
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(blockID+":"+threadID);
hash = s.toString().hashCode();
hashed= true;
}
return hash;
}
Millions of these objects are created during runtime, so I thought by making the following change, it would provide some speedup:
Version 2
@Override
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(blockID);
s.append(":");
s.append(threadID);
hash = s.toString().hashCode();
hashed = true;
}
return hash;
}
WRONG! Turns out, Version 2 is literally 100X slower than Version 1. Why???
Additional Info
I am compiling against Java 6 (customer requirement), and I am using Oracle's JVM.
My performance test involves creating a million of these objects and throwing them into a HashMap. It takes half a second to do it using Version 1, but almost 50 seconds to do it using Version 2.
hash = (blockID+":"+threadID).hashCode();blockID + ":" + threadID? And why building a String to compute the hashCode of 2 integers? Let the IDE generate the code for you: it will be much more efficient.+to be faster than usingStringBuilder- even in a loop where using aStringBuilderis supposed to be faster.