GOTCHA #5 String concatenation is expensiveObjects of the String class in .NET are immutable. An immutable object is one that can't be modified once created. What is the effect of using the + operator (or & in VB.NET) to append a String? Each call creates a new String object. This can cause object-allocation overhead and put pressure on the garbage collector. What alternative do you have? System.Text.StringBuilder provides a means for appending almost anything to a StringBuilder object. The benefits of using StringBuilder over String's +/& is illustrated in Example 1-7. Example 1-7. Using StringBuilder versus +/ &C# (StringAppend) using System; namespace StringAppendPerformance { class Test { [STAThread] static void Main(string[] args) { Console.Write("Enter number of strings to append:"); int count = Convert.ToInt32(Console.ReadLine()); string str = null; int startTick = Environment.TickCount; for (int i = 0; i < count; i++) { str = str +"."; } int endTick = Environment.TickCount; double timeTakenByPlus = (endTick - startTick) / 1000.0; System.Text.StringBuilder bldr = new System.Text.StringBuilder(); startTick = Environment.TickCount; for (int i = 0; i < count; i++) { bldr.Append("."); } endTick = Environment.TickCount; double timeTakenByStringBuilder = (endTick - startTick) / 1000.0; Console.Write("+ and StringBuilder took "); Console.WriteLine("{0} and {1} seconds", timeTakenByPlus, timeTakenByStringBuilder); } } } VB.NET (StringAppend) Module Test Sub Main() Console.Write("Enter number of strings to append:") Dim count As Integer = Convert.ToInt32(Console.ReadLine()) Dim str As String = Nothing Dim startTick As Integer = Environment.TickCount Dim i As Integer For i = 0 To count - 1 str = str &"." Next Dim endTick As Integer = Environment.TickCount Dim timeTakenByPlus As Double = _ (endTick - startTick) / 1000.0 Dim bldr As New System.Text.StringBuilder startTick = Environment.TickCount For i = 0 To count - 1 bldr.Append(".") Next endTick = Environment.TickCount Dim timeTakenByStringBuilder As Double = _ (endTick - startTick) / 1000.0 Console.Write("& and StringBuilder took ") Console.WriteLine("{0} and {1} seconds", _ timeTakenByPlus, _ timeTakenByStringBuilder) End Sub End Module Executing the above program with different values for the number of strings to append produces the results shown in Table 1-3.
The timing using the ampersand (&) in VB.NET is comparable to that of the concatenation operator (+) in C#. As the above example shows, StringBuilder is much less expensive than using + (or &) to build up a string. Furthermore, if you use StringBuilder you create fewer objects than using the +/&. This can be seen using the CLR Profiler (see "On the Web" in the Appendix). For instance, if you run 10,000 appends, the number of String instances created using +/& is 10,039. However, if you replace the +/& with StringBuilder.Append(), the number of String instances drops to 51. For an interactive client application with a few concatenations here and there, it may not make a big difference. For a server-side application, however, the difference may be significant and the use of StringBuilder is probably better. It must be noted that the instance members of a StringBuilder are not thread-safe, so you may have to take care to appropriately synchronize access to them. IN A NUTSHELLIf you find yourself appending a large number of strings, you will improve performance by using StringBuilder.Append() instead of the concatenation operators (+/&). This is especially important in server-side/backend applications. SEE ALSOGotcha #9, "Typeless ArrayList isn't type-safe" and Gotcha #21, "Default performance of Data.ReadXML is poor." |