Understanding the difference between the
String type and
StringBuilder class is really important particularly when you have a massive number of
Strings (thousands or millions) to be assigned within a loop.
If you do a normal
string concatenation in such long loops, you will end up in a performance issue and will wreak havoc in your application, especially when you have a low-resource hosting or your application is running on your client’s machine, and you never know and can never tell what are the machine specs on which your app will be running.
It is always crucial to make sure your coding is ideally optimized and properly tested in terms of memory and CPU consumption.
In this article, I will be explaining the difference between using
StringBuilder when dealing with your
string values. and in which cases you should never use
String. and other cases where
StringBuilder is not the optimal solution.
To give you a proper performance difference, I will be showcasing you a performance bench-marking between the usage of
StringBuilder when looping over a huge list of
strings and concatenating the looped values. And finally, I will provide you the equation to calculate the memory usage of your
string and other built-in methods to do this calculation for you.
String is basically an immutable sequence of characters. Each character is a Unicode character in the range U+0000 to U+FFFF. Immutable means that its state cannot be modified after it is created.
Thus, if you assign a value to a
string then reassign. The first value will stay in the memory and a new memory location will be assigned to accept the new value.
Let’s take these
string allocations for example:
String string1 = "Coding";
String string2 = "Sonata";
string3 = string1 + " " + string2;
This leads to 4 memory addresses to be allocated: Coding, Sonata, [EmptyString] , and the Concatenation between Coding and Sonata
When using the above method for a specific purpose or when you know the number of
strings to be concatenated at compile time will be few, then the wasted memory will be negligible, however, this will generate a big issue when in a loop with lots of iterations, where a
string is adding (Concatenating) to itself another
string or value, it is just constantly reallocating, in other words, it is copying to a new memory location when the memory manager can’t expand the requested amount in place. At this point, the amount of memory required (or wasted) and the processing time used for the creation of the numerous objects may become a bottleneck in the application.
This case is mostly common when, for instance, dynamically generating a TABLE and its content, or building an XML document. With this type of scenario in mind, Microsoft included the
StringBuilder class in .NET.
StringBuilder class provides the developer with a set of methods that allows manipulation of a mutable
string of characters, it can be used when you want to modify a
string without creating a new object, thus eliminating the overhead or bottleneck issue of the normal
StringBuilder class can boost performance when concatenating many strings together in a loop.
The following is a list of a few operations that can be performed to manipulate a
string using the
StringBuilder Class in .NET.
Append: Appends information to the end of the current
AppendFormat: Replaces a format specifier passed in a
string with formatted text.
Insert: Inserts a
object into the specified index of the current
Remove: Removes a specified number of characters from the current
Replace: Replaces a specified character at a specified index.
Tips for Using String and StringBuilder
StringBuilder when you’re concatenating
strings in a very long loop or in a loop within an unknown size – especially if you don’t know for sure (at compile time) how many iterations you’ll make through the loop. For example, reading a file a character at a time, building up a
string as you go.
- Use String Concatenation operator when you can specify everything which needs to be concatenated in one statement. (If you have an array of things to concatenate, consider calling
String.Concat explicitly – or
String.Join if you need a delimiter.), avoid using the (
+=) or the normal (
- If you need the intermediate results of the concatenation for something other than feeding the next iteration of concatenation,
StringBuilder isn’t going to help you. For instance, if you build up a full name from a first name and a last name, and then add a third piece of information (the nickname, maybe) to the end, you’ll only benefit from using
StringBuilder if you don’t need the (first name + last name)
string for other purpose (as we do in the example which creates a
Bench-marking String vs StringBuilder
To benchmark the difference between
StringBuilder, I prepared a simple program to measure the performance of a huge list of
strings when processed through a loop. I’ve used the Visual Studio’s diagnostics tool that displayed the CPU process percentage as well as the memory consumption.
The below code declares a gigantic list of 200K
strings starting from ‘
1000’ and upwards.
List<String> hugeList = Enumerable.Range(1000, 200000).Select(n => n.ToString()).ToList();
And here is the code that we loop through this list using the
string concatenation operation (
String concatResult = "";
foreach (String value in hugeList)
concatResult += value;
While running the code, you will notice the diagnostics tool for Visual Studio will start monitoring the memory and CPU activity.
Notice when using the
String concatenation operator
+= , even though we are updating the
concatResult variable within the loop, because
String object is immutable, it will not replace its value in the memory but it will create a new one keeping the old one intact.
So there is performance overkill when having a long loop on a
String object with the
+= concatenation operator.
Processing this list with the
string concatenation operator
+= took 2 minutes 30 seconds which is massive time and very high resource usage due to creating high number of
String objects in memory.
Now let’s boost the performance, and build our gigantic list of
strings in the loop using the correct methodology, the
The below code defines a
StringBuilder object, and then appends the
string being looped. And after that, using the
ToString() method on the
stringBuilder’s object instance, the result of appending all the
strings in the huge list can be retrieved anywhere.
StringBuilder stringBuilder = new StringBuilder();
String stringBuilderResult = "";
foreach (String s in hugeList)
stringBuilderResult = stringBuilder.ToString();
Note in the below screenshot, the total processing time for building the 200K
string object, is 99ms only.
Have you just noticed the significantly enormous difference between using
StringBuilder in such huge lists?
Bottom line: Use only StringBuilder when you want to concatenate (or build) a String when you have a large list or list of dynamic size.
Calculating String Size in Bytes
The equation to know the size of
String, for a Unicode
string with a maximum length of 2,147,483,647 characters, is as follows:
80 + [16 * Length] bits
Dim _StringSample As String = "Aramex" ‘6 Characters
Then using the
80 + (16 * 6) = 176 Bits
Same equation divided by 8, will get us the size in bytes:
(10 + [2 * Length] bytes) = 10 + (2 * 6) = 22 Bytes
Other easier and straightforward methods can include:
System.Text.Encoding – This provides methods to convert
string to bytes. Then use the
Length property to get the size in bytes directly.
Also, the below method can be used:
Encoding.GetByteCount(String) as Integer
Where you pass the
string you like and it then returns the length in Bytes.
I hope I was able to showcase the difference between
StringBuilder, and in which cases you should use any of which. Always make sure to properly understand the data structures when using data types, especially when it comes to the
String objects, since they are immutable (cannot be changed or modified).
If you think you’ve learned something new from my article, please feel free to like and share it with your peers. And if you think there was any wrong information, please let me know.