StringBuilder question

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Assuming we've defined StringBuilder myBuilder, which of the following is most expensive:

//scenario 1
myBuilder.Append("test" + "test" + "test");

//scenario 2
myBuilder.Append("test");
myBuilder.Append("test");
myBuilder.Append("test");
 
Jerry,

you mean more number of lines as expensive? or the performance?

I would say the correct way to do that may be

myBuilder.Append("test").Append("test1").Append("test2");

Shak.
 
scenario 1, because a new copy of the string is being created for each +
operation (which is why there is a StringBuilder class in the first place).

However, it's possible (because of constant folding) that may actually
compile to be myBuilding.Append("testtesttest");, in which case the second
scenario would be more expensive.
 
And of course, both are more expensive than

someString = "test" + "test" + "test";

in both lines of code and performance.
 
Right. If it does implement constant folding for literal strings that may
just become an assignment of the interned string "testtesttest" (which will
just be a object handle) to a string reference variable... like 1 IL
instruction.
 
RE: And of course, both are more expensive than someString = "test" + "test" + "test"

Let's change this scenario. Pretend there is a string variable named example. Now, which is more expensive in terms of performance & memory alloc.

//scenario 1
myBuilder.Append("test" + example + "test");

//scenario 2
myBuilder.Append("test");
myBuilder.Append(example);
myBuilder.Append("test");

//scenario 3
string myString = "test" + example + "test";


Jerry
 
scenario1 probably more expensive because of the memory copying that's going
on.

Depending on the size of the string in 'example', scenario2 would probably
be the fastest.

--
John Wood
EMail: first name, dot, last name, at priorganize.com

Jerry said:
RE: And of course, both are more expensive than someString = "test" + "test" + "test"

Let's change this scenario. Pretend there is a string variable named
example. Now, which is more expensive in terms of performance & memory
alloc.
 
Jerry said:
RE: And of course, both are more expensive than someString = "test" + "test" + "test"

Let's change this scenario. Pretend there is a string variable named
example. Now, which is more expensive in terms of performance &
memory alloc.

//scenario 1
myBuilder.Append("test" + example + "test");

//scenario 2
myBuilder.Append("test");
myBuilder.Append(example);
myBuilder.Append("test");

//scenario 3
string myString = "test" + example + "test";

Scenario 3 is the cheapest: it involves a single call to String.Concat,
which is able to work out the total length of the string, allocate the
appropriate memory, and then copy the 3 strings in place.
 
According to Rico Mariani (MS performance guru), it depends. It sounds like
something like:
someString = "test" + "test" + "test";
only counts as one concatenation, so it's not really worth a StringBuilder.

Some interesting info here:
http://weblogs.asp.net/ricom/archive/2003/12/02/40778.aspx

and here:
http://weblogs.asp.net/ricom/archive/2003/12/15/43628.aspx



Jerry said:
RE: And of course, both are more expensive than someString = "test" + "test" + "test"

Let's change this scenario. Pretend there is a string variable named
example. Now, which is more expensive in terms of performance & memory
alloc.
 
So what the hey is StringBuilder for? Can someone provide an example where using StringBuilder will be less expensive than an approach using string concatenation?
 
Yep, the third is still faster. Even doing it like
string myString = "test";
myString += example;
myString += "test";

it would still be faster than the corresponding StringBuilder (if you
include the required .ToString() ) in this specific example.

Keep in mind, even though this is a pet topic of mine, that we're talking
microseconds of difference for a single call so it's almost always better to
just write the code that looks the cleanest. I would consider that to be #3
in your specific example, but with a bit more complexity of the strings
being concatenated I would use string.Format() for that reason, even though
it is considerably slower than all these alternatives.
 
Jerry said:
So what the hey is StringBuilder for? Can someone provide an example
where using StringBuilder will be less expensive than an approach
using string concatenation?

Sure - any time you don't have all the information in some static way
to start with. For instance:

StringBuilder builder = new StringBuilder();
using (StreamReader reader = ...)
{
string line;
while ( (line=reader.ReadLine()) != null)
{
string word = ProcessLineSomehow();
builder.Append(word);
}
}
 
J.Marsch said:
According to Rico Mariani (MS performance guru), it depends. It sounds like
something like:
someString = "test" + "test" + "test";
only counts as one concatenation, so it's not really worth a StringBuilder.

Some interesting info here:
http://weblogs.asp.net/ricom/archive/2003/12/02/40778.aspx

and here:
http://weblogs.asp.net/ricom/archive/2003/12/15/43628.aspx

While I haven't been able to find where it's documented, I believe the
above actually doesn't count as *any* concatenations - it compiles to
the same code as

someString = "testtesttest";
 
I just tested this... it does. (compiles to ldstr "testtesttest")
Plus I saw constant folding listed as one of the JIT's optimization
features.
 
It's also worth noting that Concat has the following overloads:

string, string
string, string, string
string, string, string, string
string[]

So if your expression has more than four +s... it'll do quite a bit more
work (constructing an array and putting each item into the array before
calling).

Although this is probably still considerably less work than what
stringbuilder would do.
 
John Wood said:
I just tested this... it does. (compiles to ldstr "testtesttest")
Plus I saw constant folding listed as one of the JIT's optimization
features.

It shouldn't be anything to do with the JIT - it should be done at C#
compilation time, I believe.
 
BUT, you're right, I even proved this myself yesterday.
The IL that it produced included the "testtesttest", which is before the JIT
even came into play... so it is the compiler.
 
John Wood said:
http://msdn.microsoft.com/library/en-us/dndotnet/html/fastmanagedcode
.asp?frame=true

This definitely lists constant folding as a feature of the JIT... and I
would consider the automatic concatenation of that string expression as
constant folding wouldn't you?

To be honest, I'm not a big fan of that article. The idea of writing
the fastest possible code all the time is not one which appeals to me -
I far prefer to write *elegant* code which is easy to read, write and
maintain, and optimise any code which actually *needs* to be as fast as
possible.

Now, having said that, I'd have to look at exactly what is meant by
"constant folding" as far as the JIT is concerned. There may well be
things that the JIT can do which the compiler can't - they probably
have very different ideas of what a constant is. For example, suppose I
have two static readonly fields, which are initialised to some value at
runtime. The product of those fields *isn't* something the C# compiler
can compute and use once as a constant, but it *is* something the JIT
compiler might be able to do something with, depending on when it's
doing the JIT-compilation.
 
Back
Top