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.
Because you're inadvertently setting the initial capacity of the StringBuilder
instead of appending blockID
to it. See constructor documentation here.
public StringBuilder(int capacity)
Constructs a string builder with no characters in it and an initial capacity specified by the capacity argument.
Try this instead:
StringBuilder s = new StringBuilder(9);
s.append(blockID).append(':').append(threadID);
You need to check your test as your first case is actually doing.
public int hashCode(){
if(!hashed){
StringBuilder s = new StringBuilder(
new StringBuilder(blockID).append(":").append(threadID).toString());
hash = s.toString().hashCode();
hashed= true;
}
return hash;
}
In other words it is doing everything in the second case and more so it will be slower.
In short, I suspect your test is wrong, not that you are getting better performance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With