C# String Performance, Memory Usage Info

Test the performance of comparing strings. Each character in a string requires 2 bytes.

String performance. Length and character composition influence string performance. We find out if shorter strings are faster to compare—and learn how to make string comparisons faster.String Equals

We measure one aspect of the performance of strings. Longer strings take longer to compare. Each character has a cost for comparison.BenchmarkChar

Equals performance. The kind of code we test here involves 2 dynamic string variables. You can use string.Equals or "==" on these 2 strings.
Note: We use no string literals, which would be interned, placed in the executable.
String Literal
Info: The more chars that must be compared, the longer the comparison will take. A program should use the shortest string data it can.
C# program that tests string performance using System; using System.Diagnostics; class Program { static void Main() { string a1 = new string('a', 2); string a2 = new string('a', 2); string b1 = new string('a', 6); string b2 = new string('a', 6); string c1 = new string('a', 12); string c2 = new string('a', 12); int counter = 0; const int m = 100000000; // Version 1: compare 2 char strings. Stopwatch s1 = Stopwatch.StartNew(); for (int i = 0; i < m; i++) { if (a1 == a2) { counter++; } } s1.Stop(); // Version 2: compare 6-char strings. Stopwatch s2 = Stopwatch.StartNew(); for (int i = 0; i < m; i++) { if (b1 == b2) { counter++; } } s2.Stop(); // Version 3: compare 12-char strings. Stopwatch s3 = Stopwatch.StartNew(); for (int i = 0; i < m; i++) { if (c1 == c2) { counter++; } } s3.Stop(); Console.WriteLine("2 CHAR COMPARE: " + s1.ElapsedMilliseconds); Console.WriteLine("6 CHAR COMPARE: " + s2.ElapsedMilliseconds); Console.WriteLine("12 CHAR COMPARE: " + s3.ElapsedMilliseconds); Console.Read(); } } Output 2 CHAR COMPARE: 478 6 CHAR COMPARE: 551 12 CHAR COMPARE: 588

Memory. A string has some memory overhead. This is an implementation-specific detail of the String class. Studying the memory usage of strings provides insights into the object model.
Note: Each string object required a constant 16 bytes for the object data. And the buffer requires 2 bytes per character.
Therefore: The memory usage estimate for a string instance is 16 + (2 * Length) bytes.
Simulation: We run a simulation where a varying number of strings of a certain length are allocated and placed in an array.
And: The length of the array is changed to ensure the numbers remain constant for each individual string of a specific length.
String Array
C# program that measures memory usage of strings using System; class Program { static void Main() { // Loop through these sizes of string sets. // ... These are array lengths of string references. int[] sizes = { 0, 1, 100, 1000, 10000 }; foreach (int size in sizes) { // Allocate the array of references. string[] array = new string[size]; long b1 = GC.GetTotalMemory(true); // Each string is a fixed length. for (int i = 0; i < array.Length; i++) { array[i] = new string('a', 10); } long b2 = GC.GetTotalMemory(true); // Ensure the array is not optimized out of the program. if (array.Length > 0) { array[0] = null; } // Write out statistics. Console.WriteLine("Count: {0} Memory: {1} Chars: {2}", size, b2 - b1, 10 * size); } Console.ReadLine(); } } Output Count: 0 Memory: 0 Chars: 0 Count: 1 Memory: 36 Chars: 10 Count: 100 Memory: 3600 Chars: 1000 Count: 1000 Memory: 36000 Chars: 10000 Count: 10000 Memory: 360000 Chars: 100000

Notes, benchmark. The program was run in Release mode outside of the debugger. Each string occupies 16 bytes of overhead and 2 bytes for each character in its buffer.

StringBuilder. The StringBuilder type has different allocation behavior. It can use less memory. This is because it does not store separate object data if you combine many strings.StringBuilderStringBuilder Memory
Tip: You can sometimes use StringBuilder to transform many strings into a single string, allowing for fewer objects on the managed heap.

An update, 2019. The .NET Framework has become more efficient than ever before. In older versions, each string object required 20 bytes of overhead. Now the number I measure is 16.
So: Strings use less memory, which means your programs will require fewer garbage collections.

A summary. Shorter strings can be compared faster than longer ones. A string requires 16 bytes of overhead for each object, with an additional 2 bytes per character in its buffer.

© 2007-2020 Sam Allen. Send bug reports to info@dotnetperls.com.