So, you know everything about text, right? – part XI

To wrap up this series of posts about text, we’ll talk about best pratices for handling string concatenations. Since string objects are immutable, concatenating lots and lots of strings might be really bad for the performance of your application. Before going on, it’s important to understand that string concatenation *might* only be problematic at runtime. In  practice, this means that we don’t need to worry about literal string concatenations because the compiler is clever enough to build a final string from them. Here’s an example of what I’m saying:

//don't worry about this because the compiler is smart enough
//to build a unique string and embed it in the assemby metadata
var str = "This is a rather large"
            + "string which was broken to improve readability";

Whenever the compiler sees something like that, it will build the string “This is a rather large string which was broken to improve readability” and embed it in the metadata of the assembly. What we really want to solve are scenarios like the following:

//this is bad!
var watch = new Stopwatch( );
watch.Start(  );
var str = "";
for(var i = 0; i < 100000; i++) {
    str += ".!.";
}
watch.Stop(  );//around 15secs
Console.WriteLine(watch.ElapsedMilliseconds/1000.0);

In my machine, it took around 15 secs to concatenate 100000 strings. This is not a good thing. Since strings are immutable, that means that each iteration ends up creating a new string which needs to allocate memory space for all the chars. The previous code is pure evil and in these cases, you should really use the StringBuilder class:

//this is way better!!!!
var watch = new Stopwatch( );
watch.Start(  );
var str = new StringBuilder( );
for(var i = 0; i < 100000; i++) {
    str.Append( ".!.");
}
var final = str.ToString( );
watch.Stop(  );
Console.WriteLine(watch.ElapsedMilliseconds/1000.0);

Now, I’m not going to say how much time this operation took (try it:)), but I will say that it was really really fast…Proficient developers know that we could improve the performance of the previous code by setting the total size of the buffer during the StringBuilder instantiation (notice that in the previous code it’s fairly easy to know the required sized of the buffer).

When developers that are getting started look at the previous examples, they think that they probably should be using StringBuilder instances everywhere…Here’s some code I’ve found before:

var firstName = "Luis";
var lastName = "Abreu";
var bld = new StringBuilder( );
bld.Append( firstName );
bld.Append( "-" );
bld.Append( lastName );

In the previous snippet I’ve introduced variables to simulate receiving input from the user. The first thing you should notice is that we’re just concatenating 3 strings. That’s it! In these cases, you should simply concatenate the strings:

var firstName = "Luis";
var lastName = "Abreu";
var total = firstName + "-" + lastName;

Whenever the compiler sees that you’re using the + operator to concatenate strings, it will automatically transform that into a Concat method call:

var firstName = "Luis";
var lastName = "Abreu";
var total = String.Concat( firstName, "-", lastName );

There are several overloads of the Concat method. The most interesting thing about this method is that it will start by creating a buffer big enough for copying all the strings it receives, so you’ll only have one string instantiation (unlike the initial code shown in the for loop earlier).

What I’m trying to say is that you should *only* use the StringBuilder type when you’re doing lots and lots of concatenations inside a loop (ex.: getting chars from the user). When you’re working with a small number of strings variables, then you should use the String.Concat method (or the + operator, if you think it improves readability).

And that’s it for now. Stay tuned for more.

Advertisements

~ by Luis Abreu on May 13, 2011.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: