String Concatenation

I l @ ve RuBoard

It can be surprising how much negative impact string concatenation can have on your application's performance. String concatenation has always been the bane of the Visual Basic programmer. Previous versions of Visual Basic provided no alternatives to the & operator, which is slow. The reasons for this were fairly straightforward. Take the following example:

 DimsAsString s= "SelectFName,LNameFromAuthorsWhereLNameLike'%" &name& "%'" 

You might not know it, but Visual Basic cannot combine two strings per se. What it does is create a new string object that contains the combined source strings' values. Using the & results in a new string being created each time you use it (unless it is used in a Const statement, in which case it is evaluated at compile time). The above example causes the creation of three strings just to assign one to the variable s . This leads to unnecessary ”or at least unwanted ”memory allocation to build just one string. And it gets much worse as you add more to the string.

Desperate developers have had to resort to creating custom COM components to do string concatenation efficiently . Others have just lived with the problem or have never been aware of it in the first place. Visual Basic .NET finally has an answer to the problem, thanks to the .NET Framework: StringBuilder .

Note

String concatenation using the & operator does not work much differently in Visual Basic .NET compared to earlier versions of Visual Basic. It is still inherently inefficient, but that doesn't mean you should never use it. It is still useful and relatively lightweight for minimal string concatenation. However, when performance is key and you have to do a lot of string concatenation, you need to look at alternatives.


StringBuilder Makes the Grade

The System.Text.StringBuilder class finally gives Visual Basic developers the tools they need to do efficient string manipulation operations. StringBuilder provides a buffer-oriented mechanism to manipulate string information. String concatenation is not its only use, but that's the most common one. The following example shows how to use StringBuilder to perform a concatenation task equivalent to the previous example:

 DimsAsString DimsbAsNewStringBuilder() sb.Append("SelectFName,LNameFromAuthorsWhereLNameLike'%") sb.Append(name) sb.Append("%'") s=sb.ToString() 

It's amusing to think that this example, which uses more code than the first example, actually runs faster and is more efficient (if you ignore the cost of creating the StringBuilder object). This demonstrates the cardinal rule of performance: less code does not always run faster.

Note

StringBuilder doesn't manipulate a string per se. Strings are immutable. StringBuilder is just a wrapper for a buffer of characters that you can manipulate in interesting ways. When you call the ToString method of StringBuilder , that's when a true string object is created.


You can tune the performance of StringBuilder by specifying its initial buffer size . When you create a default instance of a StringBuilder (when you use the constructor without arguments), StringBuilder allocates a default buffer of 16 characters. If, however, you know that you'll be creating a very large string (or if you at least know the ballpark size), you can specify the initial capacity of the buffer. This allows StringBuilder to avoid most or all additional memory allocation as strings are appended to it. Don't take this as an argument for always creating large buffers. For most operations, you probably needn't worry, but it is always useful to know that you can tweak things if you need to.

Note

Don't assume that StringBuilder is always more efficient than the & operator. When you have a very simple string that requires minimal use of & , StringBuilder is not really appropriate. Remember that you have to create a new instance of the StringBuilder class, and that's not free. In order for you to realize a performance gain, the equivalent concatenation operation must be slower than the combined work of creating a StringBuilder , doing the necessary work, and then converting the result to a string (using ToString ).


Format Strings

The string formatting mechanism provided by the .NET Framework is extremely powerful. In fact, you've already seen it used countless times in this book with the Console.WriteLine method. It offers an exciting addition to Visual Basic's capabilities: very fine control over how strings are built and how different types and values are represented in strings. This mechanism is extremely flexible and enables you to generate sophisticated customized string output very easily. The simplest form looks like the following example:

 Console.WriteLine("Thisisa{0}", "test") Console.WriteLine("Thisis{0}{1}", "another", "test") 

The WriteLine method supports using a string input, with an argument list. You can see how easy it is to have values inserted into the string. This is a very easy-to-read way to build strings. Format strings are used in many ways through the .NET Framework's type system, but here we're interested only in the String.Format method and the StringBuilder.AppendFormat method. The following example demonstrates the use of both:

 DimsbAsNewStringBuilder() sb.AppendFormat(_  "SelectFName,LNameFromAuthorsWhereLNameLike'%{0}%'",name) DimsAsString=String.Format(_  "SelectFName,LNameFromAuthorsWhereLNameLike'%{0}%'",name) 

I have to admit that I really like the format methods and use them often. When performance is not critical, this approach can be an effective and readable way to deal with strings. You can safely assume that the rules for string concatenation apply to format strings as well. In other words, for small concatenation operations, using the String.Format method is probably more efficient than using the StringBuilder.AppendFormat method. When you start increasing the number of concatenation operations, however, StringBuilder becomes the clear winner. We'll look at this more closely in the next section.

Note

Things get even more interesting when you look at how to format numbers and how you can manipulate the string output. Unfortunately, I can't even attempt to do justice to this topic here. If you're interested in how to do more with format strings, search the Visual Studio .NET Help documentation for "Formatting Overview" using the "Visual Basic and Related" filter and select the Search In Titles Only check box.


String Performance by the Numbers

So far, I've shown you four ways to create strings and essentially told you which methods are preferable and when. But don't take my word for it. For the sake of demonstrating the performance advantages and disadvantages of the different forms of string concatenation, I created four methods: StringContact , StringFormat , StringBuilder , and StringBuilderFormat . Here's what they look like:

 SubStringConcat() DimiAsInteger DimsAsString Fori=0ToMAX_LOOP s= "InsertIntoAuthors(au_lname,au_fname,phone, " _ & "address,city,state,zip,contract)Values(" s&= "'" &lName& "'," s&= "'" &fName& "'," s&= "'" &phone& "'," s&= "'" &address& "'," s&= "'" &city& "'," s&= "'" &state& "'," s&= "'" &zip& "'," s&=contract.ToString()& ")" Next EndSub PrivatesbasNewStringBuilder() SubStringBuilderConcat() DimsAsString DimiAsInteger Fori=0ToMAX_LOOP sb.Append("InsertIntoAuthors(au_lname,au_fname,phone, " _ & "address,city,state,zip,contract)Values(" sb.Append("'") sb.Append(lName) sb.Append("','") sb.Append(fName) sb.Append("','") sb.Append(phone) sb.Append("','") sb.Append(address) sb.Append("','") sb.Append(city) sb.Append("','") sb.Append(state) sb.Append("','") sb.Append(zip) sb.Append("',") sb.Append(contract) sb.Append(")") s=sb.ToString() sb.Length=0 Next EndSub SubStringBuilderFormat() DimsAsString DimiAsInteger Fori=0ToMAX_LOOP sb.Append("InsertIntoAuthors(au_lname,au_fname,phone, " _ & "address,city,state,zip,contract)Values(" sb.AppendFormat("'{0}','{1}', ",lName,fName) sb.AppendFormat("'{0}','{1}', ",phone,address) sb.AppendFormat("'{0}','{1}', ",city,state) sb.AppendFormat("'{0}',{1})",zip,contract) s=sb.ToString() sb.Length=0 Next EndSub SubStringFormat() DimiAsInteger DimsAsString Fori=0ToMAX_LOOP s= "InsertIntoAuthors(au_lname,au_fname,phone, " _ & "address,city,state,zip,contract)Values(" s&=String.Format("Values('{0}','{1}', ",lName,fName) s&=String.Format("'{0}','{1}', ",phone,address) s&=String.Format("'{0}','{1}', ",city,state) s&=String.Format("'{0}',{1})",zip,contract) Next EndSub 

Using the test application StringConcatPerformance (which is included with this chapter's sample files), I put these methods through their paces. The results are as follows :

 NormalFormat Concat680.981341.931.97timesslowerthanStringConcat StringBuilder410.59911.312.22timesslowerthanStringBuilder 1.66x1.47x 

Let's discuss these results for a moment. Comparing string concatenation and StringBuilder.Append , you can see that it took about half the time to run the StringBuilder method. This is a significant difference. You can also see that the difference is only slightly less when you compare String.Format and StringBuilder.AppendFormat . What might be surprising is how much slower in general the format methods are. In retrospect, this does make some sense. Using format strings requires parsing the input string and generating the specific variable formats, whereas the "Normal" methods require only combining strings ”nothing more.

Note

Your numbers will vary depending on your system. My machine isn't quite as fast as it used to be, but the relationships between the samples should remain roughly similar ”unless, of course, work is done on future releases of the CLR to improve string performance (something I consider highly likely).


You should also note that StringBuilder.AppendFormat is only slightly slower than regular string concatenation. This is interesting because StringBuilder.AppendFormat is far more flexible and easier to work with.

Note

If you're using StringBuilder , I recommend a mix of calls to Append and AppendFormat . Calling AppendFormat with only a string and no arguments is a waste of resources.


I l @ ve RuBoard


Designing Enterprise Applications with Microsoft Visual Basic .NET
Designing Enterprise Applications with Microsoft Visual Basic .NET (Pro-Developer)
ISBN: 073561721X
EAN: 2147483647
Year: 2002
Pages: 103

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net