This week's book giveaway is in the JavaScript forum.
We're giving away four copies of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js and have Paul Jensen on-line!
See this thread for details.
Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

StringBuffer performance  RSS feed

 
Sajee Joseph
Ranch Hand
Posts: 200
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello all,
Everyone is aware of that StringBuffers should be preffered over Strings when several cantenations are involved. However isn't it true that it is necessary to guess the capacity of the StringBuffer than use the default capacity. In other words, consider the following code:
StringBuffer sBufferData = new StringBuffer();
String sSomeVeryLargeData = "someVeryLargeData..someVeryLargeData..some..";
for(int i = 0; i < 25 ; i++)
{
sBufferData.append(sSomeVeryLargeData + i);
}
Now in this case isn't my StringBuffer as bad as my String, since my StringBuffer is appending more that 16 characters at a time, it will have to out grow and find new space in each iteration of 'i'.
Can someone answer this?
Regards,
Sajee Joseph
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm going to move this to the Performance forum since that's what we specialize in there.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
However isn't it true that it is necessary to guess the capacity of the StringBuffer than use the default capacity.
It's desireable, if you want to get the best possible perfornance from StringBuffer, to preallocate it to the desired size. If that's possible. If not, you certainly shouldn't think presizing is a requirement - you still get pretty good results from a StringBuffer, often substantially better than you would from repeated use of the + concatenation operator in a loop.
[B]In other words, consider the following code:

Now in this case isn't my StringBuffer as bad as my String, since my StringBuffer is appending more that 16 characters at a time, it will have to out grow and find new space in each iteration of 'i'.[/B]
Not on every iteration, no. Because by default, whenever the StringBuffer resiszes itself, it will double its size. Actually it's double + 2, or more if that's not enough to handle whatever is being appended at one time. E.g. if we start with an empty StringBuffer with capacity 16, and append a 50-char string repeatedly:

The resizes are marked with asterisks. So what happens is the the first few times through the loop you resize frequently - but the more times you go through the loop, the less frequently the resizes occur. On a big loop, the number of resizes will end up fairly small compared to the number of iterations, and so StringBuffer performance will still be pretty good compared to any technique that requires rebuffering on each iteration. Still, if you can presize the StringBuffer to avoid any resizing, that will be even better.
Incidentally you can also improve the performance of your solution by replacing

with

This is a minor point, and also reduces readability a bit, so it's your decision if it's worth it.
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Sajee Joseph:
Everyone is aware of that StringBuffers should be preffered over Strings when several cantenations are involved.

I think this is stated too generally. I would say that you should prefer StringBuffers over Strings *when you get performance problems* because of several concatenations. Often you will find that they don't present a bottleneck - and in those cases I still prefer the better readability of Strings.
Or more generally speaking: per default, readability trumps performance.
 
Yuriy Grechukhin
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Often you will find that they don't present a bottleneck - and in those cases I still prefer the better readability of Strings.


Good point, I just wanna add that sometimes StringBuffer makes the code more readable. Consider this example:

instead of

[ February 04, 2004: Message edited by: Yuriy Grechukhin ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mmm, actually that's an example where I consider the short form to be slightly more readable on its own, and preferable in terms of not wasting space, which makes it easier to find everything else in the class. And the StringBuffer really provides no benefit at all here in terms of performance anyway; the two methods will probably compiler to the exact same bytecode (or nearly so).
My own rule of thumb is that I'll use a StringBuffer any time I'm building a string within a loop, otherwise no. It's a simple enough rule that I can just do it, and move on to something more important. What's "readable" is often defined by what you're used to seeing; I'm used to using a StringBuffer inside a loop, and have no problem at all reading it. Different people have different tastes though, so if I have lots of co-workers who prefer +, I'll probably defer to them.
 
David Weitzman
Ranch Hand
Posts: 1365
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
On a slightly more technical note, it is typical (as Jim's numbers show) for data structures like vectors and hashtables to at least double in size when it's time to grow. There's actually a good reason for this.
Suppose you have an array of N items and the time you spent populating the array was proportional to the size of the array. That means there's some constant k such that the time spent populating the array is kN. Now suppose you double the size of the array and it takes 2cN time to allocate 2N spaces (where c is just another constant for the time it takes to allocate an array of size c) in addition to kN time to copy over the original elements. If you spend another kN units of time filling in what's left the the new array, you've spent a total of kN + 2cN + 2kN or (1.5k+c)2N units of time to fill 2N spaces.
So building an array with N elements always takes order N time, even if larger numbers mean a larger constant factor. If StringBuffer made a habit of always allocating 50 more spaces instead of N more, performance for quickly growing strings would be absolutely unbearable.
You can get an idea of the number of expected resizes with the formula expectedResizes = Math.ceil(Math.log(N)/Math.log(2))-4. That'll be larger than the actual number since StringBuffer grows a little faster.
 
michael yue
Ranch Hand
Posts: 204
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Does the use of StringBuffer solve the problem of out of memory? Has anyone successfully use StringBuffer to solve this problem?
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by rollin park:
Does the use of StringBuffer solve the problem of out of memory? Has anyone successfully use StringBuffer to solve this problem?

What problem are you referring too? There are certainly many ways to get an out of memory problem, but I am not aware of one which would be solved by using a StringBuffer.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!