String Performance Part Two - String Concatenation
Dec
4
Written by:
12/4/2008
In a follow-up to my previous post about string performance, I decided to do more of side-by-side comparison of the most common string concatenation techniques.
We all know these common techniques to be using the typical concatenation characters (& or +), String.Concat, and the StringBuilder. I have read many times and saw pretty graphs telling me about how high performing the String.Concat method is over the traditional concatenation method. I was highly surprised to find results to contradict these findings in my own testing.
So here is how I set-up this testing... I created a Console Application and created code to build out a list of a string object, and put that information into a dynamically generated HTML table. The code used to perform this is at the bottom of the blog entry. Within the HTML table code, I left it open to repeat the table row generation from the list object. This way, we can run as many iterations through string objects as we want.
The first test went as expected. I ran through a single iteration. The standard concatenation method was the only method to cost more than 0 milliseconds.

Bumping the iterations from 1 to 5 began to show me something I didn't expect. The String.Concat method and standard concatenation ran even with each other at 15 milliseconds, versus the StringBuilder which was still 0 milliseconds.

Doubling the iterations at 10 showed us that the String.Concat method was beginning to slow down in comparison to the standard concatenation method. The StringBuilder was still running under 0 milliseconds.

The previous finding remained true until we approach 500 iterations. Once there, we begin to see the StringBuilder actually spend some ticks getting finished. The other methods take longer, but the percentages are the same.

This puts a kink in the way I do things and what I have witnessed to work (outside of benchmarks). So I am not sure how I will proceed at this point.
Here is the code used to determine these findings:
Private Sub StringConcatenationCompare()
Dim strOutput As String = String.Empty
Dim sbOutput As New Text.StringBuilder
' get a list of string objects to concatenate later
Dim lstCustomer As New List(Of Customer)
lstCustomer = GetCustomerList()
' create the timer objects
Dim dteStart As DateTime = Nothing
Dim spnTime As TimeSpan = Nothing
' set up a counter to reiterate through concantenations to simulate a high load
Dim intCount As Integer = 500
Console.WriteLine(String.Format("Testing the conditions {0} times.", intCount.ToString))
'
' BEGIN NORMAL CONCATENATION
'
Console.WriteLine(Environment.NewLine)
Console.WriteLine("TEST CONDITION:")
Console.WriteLine("strOutput += ""<td>"" + item.FirstName + "" "" + item.LastName + ""</td>""")
' build a table of customers
dteStart = DateTime.Now
strOutput = "<table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">"
strOutput += "<tr>"
strOutput += "<td>Full Name</td>"
strOutput += "<td>First Name</td>"
strOutput += "<td>Last Name</td>"
strOutput += "<td>City</td>"
strOutput += "<td>State</td>"
strOutput += "</tr>"
For intI As Integer = 0 To intCount
For Each item As Customer In lstCustomer
strOutput += "<tr>"
strOutput += "<td>" + item.FirstName + " " + item.LastName + "</td>"
strOutput += "<td>" + item.FirstName + "</td>"
strOutput += "<td>" + item.LastName + "</td>"
strOutput += "<td>" + item.City + "</td>"
strOutput += "<td>" + item.State + "</td>"
strOutput += "</tr>"
Next
Next
strOutput += "</table>"
' display time of output
spnTime = DateTime.Now.Subtract(dteStart)
Console.WriteLine(String.Format("Standard concatenation took {0} milliseconds.", spnTime.Milliseconds.ToString))
' BEGIN reset
strOutput = String.Empty
' END reset
'
' BEGIN String.Concat CONCATENATION
'
Console.WriteLine(Environment.NewLine)
Console.WriteLine("TEST CONDITION:")
Console.WriteLine("strOutput = String.Concat(strOutput, ""<td>"", item.FirstName, "" "", item.LastName, ""</td>""")
' build a table of customers
dteStart = DateTime.Now
strOutput = "<table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">"
strOutput = String.Concat(strOutput, "<tr>")
strOutput = String.Concat(strOutput, "<td>Full Name</td>")
strOutput = String.Concat(strOutput, "<td>First Name</td>")
strOutput = String.Concat(strOutput, "<td>Last Name</td>")
strOutput = String.Concat(strOutput, "<td>City</td>")
strOutput = String.Concat(strOutput, "<td>State</td>")
strOutput = String.Concat(strOutput, "</tr>")
For intI As Integer = 0 To intCount
For Each item As Customer In lstCustomer
strOutput = String.Concat(strOutput, "<tr>")
strOutput = String.Concat(strOutput, "<td>", item.FirstName, " ", item.LastName, "</td>")
strOutput = String.Concat(strOutput, "<td>", item.FirstName, "</td>")
strOutput = String.Concat(strOutput, "<td>", item.LastName, "</td>")
strOutput = String.Concat(strOutput, "<td>", item.City, "</td>")
strOutput = String.Concat(strOutput, "<td>", item.State, "</td>")
strOutput = String.Concat(strOutput, "</tr>")
Next
Next
strOutput = String.Concat(strOutput, "</table>")
' display time of output
spnTime = DateTime.Now.Subtract(dteStart)
Console.WriteLine(String.Format("String.Concat concatenation took {0} milliseconds.", spnTime.Milliseconds.ToString))
'
' BEGIN StringBuilder CONCATENATION
'
Console.WriteLine(Environment.NewLine)
Console.WriteLine("TEST CONDITION:")
Console.WriteLine("(used the stringbuilder)")
' build a table of customers
dteStart = DateTime.Now
sbOutput.Append("<table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">")
sbOutput.Append("<tr>")
sbOutput.Append("<td>Full Name</td>")
sbOutput.Append("<td>First Name</td>")
sbOutput.Append("<td>Last Name</td>")
sbOutput.Append("<td>City</td>")
sbOutput.Append("<td>State</td>")
sbOutput.Append("</tr>")
For intI As Integer = 0 To intCount
For Each item As Customer In lstCustomer
sbOutput.Append("<tr>")
sbOutput.Append("<td>")
sbOutput.Append(item.FirstName)
sbOutput.Append(" ")
sbOutput.Append(item.LastName)
sbOutput.Append("</td>")
sbOutput.Append("<td>")
sbOutput.Append(item.FirstName)
sbOutput.Append("</td>")
sbOutput.Append("<td>")
sbOutput.Append(item.LastName)
sbOutput.Append("</td>")
sbOutput.Append("<td>")
sbOutput.Append(item.City)
sbOutput.Append("</td>")
sbOutput.Append("<td>")
sbOutput.Append(item.State)
sbOutput.Append("</td>")
sbOutput.Append("</tr>")
Next
Next
sbOutput.Append("</table>")
' display time of output
spnTime = DateTime.Now.Subtract(dteStart)
Console.WriteLine(String.Format("StringBuilder concatenation took {0} milliseconds.", spnTime.Milliseconds.ToString))
End Sub
Private Function GetCustomerList() As List(Of Customer)
Dim lstCustomer As New List(Of Customer)
Dim objCustomer As Customer = Nothing
objCustomer = New Customer
With objCustomer
.FirstName = "John"
.LastName = "Dough"
.City = "Orlando"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Bill"
.LastName = "Gates"
.City = "Seattle"
.State = "WA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Barack"
.LastName = "Obama"
.City = "Washington"
.State = "DC"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "John"
.LastName = "McCain"
.City = "Phoenix"
.State = "AR"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Keanu"
.LastName = "Reeves"
.City = "Hollywood"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Stephen"
.LastName = "Colbert"
.City = "New York"
.State = "NY"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Jason"
.LastName = "Bourne"
.City = "Anytown"
.State = "USA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "LaDanian"
.LastName = "Tomlinson"
.City = "San Diego"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Clinton"
.LastName = "Hart"
.City = "Ocala"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Henry"
.LastName = "Ford"
.City = "Detroit"
.State = "MI"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Michael"
.LastName = "Turner"
.City = "Atlanta"
.State = "GA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Grant"
.LastName = "Wilson"
.City = "Warwick"
.State = "RI"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Claire"
.LastName = "Bennett"
.City = "Costa Mesa"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Michael"
.LastName = "Schofield"
.City = "Joliet"
.State = "IL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Drew"
.LastName = "Brees"
.City = "New Orleans"
.State = "LA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Criss"
.LastName = "Angel"
.City = "Las Vegas"
.State = "NV"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Rex"
.LastName = "Grossman"
.City = "Chicago"
.State = "IL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Antonio"
.LastName = "Cromartie"
.City = "Tallahassee"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Dan"
.LastName = "Marino"
.City = "Miami"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Hulk"
.LastName = "Hogan"
.City = "Tampa"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Michael"
.LastName = "Winslow"
.City = "Orlando"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Kurt"
.LastName = "Angle"
.City = "Orlando"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "John"
.LastName = "Travolta"
.City = "Ocala"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Leo"
.LastName = "LaPorte"
.City = "San Francisco"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Kevin"
.LastName = "Rose"
.City = "San Francisco"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Mohinder"
.LastName = "Suresh"
.City = "New York"
.State = "NY"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Stephen"
.LastName = "King"
.City = "Bangor"
.State = "ME"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Dan"
.LastName = "Fouts"
.City = "San Diego"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Junior"
.LastName = "Seau"
.City = "San Diego"
.State = "CA"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Kurt"
.LastName = "Warner"
.City = "Phoenix"
.State = "AZ"
End With
lstCustomer.Add(objCustomer)
objCustomer = New Customer
With objCustomer
.FirstName = "Russ"
.LastName = "Rollins"
.City = "Orlando"
.State = "FL"
End With
lstCustomer.Add(objCustomer)
Return lstCustomer
End Function
Public NotInheritable Class Customer
Private p_FirstName As String
Private p_LastName As String
Private p_City As String
Private p_State As String
Public Property FirstName() As String
Get
Return p_FirstName
End Get
Set(ByVal value As String)
p_FirstName = value
End Set
End Property
Public Property LastName() As String
Get
Return p_LastName
End Get
Set(ByVal value As String)
p_LastName = value
End Set
End Property
Public Property City() As String
Get
Return p_City
End Get
Set(ByVal value As String)
p_City = value
End Set
End Property
Public Property State() As String
Get
Return p_State
End Get
Set(ByVal value As String)
p_State = value
End Set
End Property
End Class
Technorati Tags: Strings ,Performance ,VB
Copyright ©2008 Will Strohl