One of the common criticisms levelled at me from certain types of developers (a type which really needs its own name) is that when I’m building a large string, I don’t always use StringBuilder. For example, when I’m building an SQL statement, I simply concatenate the lines of the statement using the & operator. For example:


Command.CommandText = _
( _
  "INSERT INTO [PrintMargins]" _
  & " (" _
  & "   [PrinterName]," _
  & "   [LeftMargin]," _
  & "   [RightMargin]," _
  & "   [TopMargin]," _
  & "   [BottomMargin]" _
  & " )" _
  & " VALUES" _
  & " (" _
  & "   @PrinterName," _
  & "   @LeftMargin," _
  & "   @RightMargin," _
  & "   @TopMargin," _
  & "   @BottomMargin" _
  & " )" _
)

Command.Parameters.Add("@PrinterName", PrinterName)
Command.Parameters.Add("@LeftMargin", Margins.Left)
etc.

Unless a profiler showed me that this code was causing a bottleneck due to the building of the string taking a great deal of time, there’s no way I would even have considered using a StringBuilder here.

The likelihood that a few (about 15?) string concatenations would be anywhere near significant in the time taken to perform this operation on the RDBMS just seems incredibly low to me, based on my experience with various other platforms and languages.

I would also guess that the compiler might take a pair of string constants with the ‘&’ operator between them and simply concatenate them at compile time, though I wouldn’t assume so.

Of course, as a humble developer, I’m always willing to bow to the measurements of the profiler and, having worked with Microsoft’s development products for some time, would not have been too shocked to learn that a bug (sorry, ‘by-design feature’) in the compiler would cause concatenations like the above to eat several seconds of CPU. As a developer, you can’t make too many assumptions.

I was taken to task for just this kind of concatenation (constant strings). So I benchmarked it.


Function TestConcat As String

  Dim Lyrics As String = "Shower in the dark day" _
  & "Clean sparks diving down" _
  & "Cool in the waterway" _
  & "Where the baptised drown" _
  & "Naked in the cold sun" _
  & "Breathing life like fire" _
  & "Thought I was the only one" _
  & "But that was just a lie" _
  & "Heard it in the wind" _
  & "Saw it in the sky" _
  & "Thought it was the end" _
  & "Thought it was fourth of July" _

  Return Lyrics

End Function

Function TestStringBuilder As String

  Dim LyricsBuilder As New StringBuilder("Shower in the dark day")

  LyricsBuilder.Append("Clean sparks diving down")
  LyricsBuilder.Append("Cool in the waterway")
  LyricsBuilder.Append("Where the baptised drown")
  LyricsBuilder.Append("Naked in the cold sun")
  LyricsBuilder.Append("Breathing life like fire")
  LyricsBuilder.Append("Thought I was the only one")
  LyricsBuilder.Append("But that was just a lie")
  LyricsBuilder.Append("Heard it in the wind")
  LyricsBuilder.Append("Saw it in the sky")
  LyricsBuilder.Append("Thought it was the end")
  LyricsBuilder.Append("Thought it was fourth of July")

  Return LyricsBuilder.ToString()

End Function

Sub Main

  Dim Start As DateTime
  Const Iterations As Integer = 10000000

  Start = DateTime.Now

  For i As Integer = 1 To Iterations: TestConcat: Next i

  Console.WriteLine(DateTime.Now.Subtract(Start).TotalMilliseconds.ToString)

  Start = DateTime.Now

  For i As Integer = 1 To Iterations : TestStringBuilder: Next i

  Console.WriteLine(DateTime.Now.Subtract(Start).TotalMilliseconds.ToString)

  Console.ReadLine

End Sub

Results with debugging on:


78.1265
19484.7491

Results with debugging off:


0
19344.1214

The compiler may have optimised away my calls to TestConcat when debugging was off, but I think it’s pretty obvious that using StringBuilder in this situation does not speed up the code.

There’s an article here measuring the performance of StringBuilder as compared to concatenation - where the strings are concatenated in a loop - and the compiler can’t optimise away that concatenation. I measured this myself some time ago and came to the same conclusion.

No comments