| I l @ ve RuBoard |
String Concatenation
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
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
Desperate developers have had to resort to creating custom COM
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
StringBuilder Makes the GradeThe 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
Note
StringBuilder
doesn't manipulate a string per se. Strings are immutable.
StringBuilder
is just a wrapper for a buffer of
You can tune the performance of
StringBuilder
by specifying its initial buffer
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 StringsThe 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
Note
Things get even more interesting when you look at how to format
String Performance by the Numbers
So far, I've shown you four ways to create strings and
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
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
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 |