Reputation: 1190
I'm aware of the difference between concat, StringBuffer and StringBuilder. I'm aware of the memory issue with the StringBuffer.toString backing array which can explode memory. I'm even aware of the JDK Sun optimization consisting in allocation a power of two for initial capacity.
But I'm still wondering about the best way to reuse a StringBuffer (used in toString()) or, if reusing the StringBuffer is pertinent. Which one is better with memory and speed performance in mind ?
public String toString2() {
StringBuffer sb = new StringBuffer(<size>)
... several .append(stuff) ...
sb.trimToSize()
return sb.toString()
}
or
private StringBuffer sb = new StringBuffer(<size>)
public String toString2() {
sb.delete()
sb.setLength(1024)
sb.trimToSize()
... several .append(stuff) ...
return sb.toString()
}
And why ?
Upvotes: 2
Views: 3852
Reputation: 35008
Try performance testing both. As with all questions of performance it'll depend on the context and how the methods are called.
A couple of notes:
StringBuilder
is not thread-safe, but in your 1st example thread-safety is not an issue as your method is not using an fields. This makes StringBuilder
faster than StringBuffer
.StringBuffer
, so you'll end up with a string that contains elements from both calls.StringBuffer
around (2nd example), depending on how often you use the method, you may actually be holding on to more memory because the garbage collector will not collect the memory used by the StringBuffer
, which could be used by other objects.Upvotes: 0
Reputation: 200148
StringBuilder
, a non-synchronized variant of StringBuffer
-- that gives you a performance boost straight out of the box. trimToSize
-- you are just forcing the StringBuilder
to make a new char array.StringBuilder
since the JVM is highly optimized for the allocation of short-lived objects.StringBuilder
instead of a simple concatenation expression only if you cannot express your string in a single expression -- for example, you are iterating over some stuff. Concatenation compiles to basically the same code using the StringBuilder
.Upvotes: 2
Reputation: 116266
I would say the first example is definitely clearer, easier to read and safer - which should almost always trump performance micro-optimization concerns. If you do have a performance problem, and you can prove (with concrete measurements) that it is caused by this piece of code, and you can also prove by measurement that in your local environment, the 2nd example is significantly faster, then - and only then - you have a valid reason to use that.
Otherwise, there is no general answer to your question. What would it help you if people claimed that the 2nd example were faster by n% on average, if it doesn't make any difference on your machine (either because of a different environment, or because the actual piece of code is called so rarely in your app)?
However, my personal gut feeling is that on a modern JVM (read: at least on JDK6, but possibly already on JDK5), the first example might actually be faster, due to clever GC tricks making allocation / deallocation of short-lived objects extremely cheap. Especially so if you used a StringBuilder
instead of StringBuffer
, which has no synchronization overhead.
Upvotes: 3
Reputation: 533492
I wouldn't use StringBuffer at all esp if performance is a concern.
If you can't be sure that only one thread will call toString(), I would create a StringBuilder each time.
The other problem you have is that different data types can create a lot of garbage e.g. int
or double
and this can reduce any benefit you might achieve.
I wouldn't recycle StringBuilder, I would just keep things simple. If you really need the maximum performance I would use a different solution like a direct ByteBuffer with a library which creates no garbage.
Upvotes: 0