C# string.Intern

String type

string.Intern optimizes string memory and performance. It allows you to put strings in the runtime's shared string pool. We look at the Intern method. We then benchmark and analyze some code in the C# programming language.

This C# article covers the string.Intern method. It reviews the shared string pool.

Introduction

.NET Framework information

The Intern static method can improve performance of string comparisons by more than two times. However, you shouldn't use it very often. string.Intern puts strings in a common string pool maintained by the .NET runtime. The string pool is an optimization mainly for string literals. Here, we note that string literals are simply strings that you place directly in your code. They are surrounded by quotes. They are constant and immutable—meaning you can't change them.

Program that uses string.Intern [C#]

class Program
{
    static void Main()
    {
	// Figure s1.
	// Regular string literal.
	string s1 = "I'm a string literal.";

	// Figure s2.
	// Const string literal.
	const string s2 = "I'm also a string literal.";

	// Figure s3.
	// Verbatim string literal.
	string s3 = @"I'm a string literal
with the verbatim syntax.";
    }
}

Change string literals

You cannot change string literals. However, you can reassign the variable that points to them. This changes the reference, not the value. In this program, we demonstrate that the reference is only changed.

Program that reassigns string literals [C#]

class Program
{
    static void Main()
    {
	string s = "I'm a string literal.";
	s = "I'm another literal.";
    }
}

More details

Note

The string.Intern method takes a string you build up at runtime programmatically and basically turns it into a string literal. This makes comparisons much faster. MSDN says that the Intern method uses the intern pool to search for a string equal to the value. If the string does not exist, a reference to str is added to the intern pool, then that reference is returned.

MSDN reference
Program that interns string [C#]

class Program
{
    static void Main()
    {
	// A.
	// String generated at runtime.
	// Is not unique in string pool
	string s1 = new StringBuilder().Append("cat").Append(" and dog").ToString();

	// B.
	// Interned string added at runtime.
	// Is unique in string pool.
	string s2 = string.Intern(s1);
    }
}

Compare intern strings

It is faster to compare interned strings because the method that C# implements string comparisons with always checks references first. If the references are equal, the comparison succeeds.

Implementation of string.Equals [C#]

public static bool Equals(string a, string b)
{
    return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b)));
}

Note: The Equals method above is how the == operator is implemented in the .NET Framework. The very first part tests the references for equality. EqualsHelper compares all the characters in a loop and is slower.

Performance

My benchmark shows that the string.Intern improves performance by more than 4x when the string comparison is always true. For the example, one comparison is false and one is true.

Program that compares performance [C#]

using System;
using System.Text;

class Program
{
    static void Main()
    {
	// 1.
	// Create string at runtime.
	StringBuilder b = new StringBuilder().Append("cat ").Append(
	    "and ").Append("dog");
	// 2.
	// Get runtime string.
	string s1 = b.ToString();
	// 3.
	// Get string pool reference to string.
	string s2 = string.Intern(s1);

	// 4.
	// Three loops:
	// - Repeat benchmark 10 times
	// - Repeat inner loop 10000 times
	// - Repeat 2 tests 10000 times
	int m = 10000;
	for (int v = 0; v < 10; v++)
	{
	    int d = 0;
	    long t1 = Environment.TickCount;

	    // 5.
	    // Test regular string.
	    for (int i = 0; i < m; i++)
	    {
		for (int a = 0; a < m; a++)
		{
		    if (s1 == "cat and rabbit")
		    {
			d++; // false
		    }
		    if (s1 == "cat and dog")
		    {
			d--; // true
		    }
		}
	    }
	    long t2 = Environment.TickCount;

	    // 6.
	    // Test interned string.
	    for (int i = 0; i < m; i++)
	    {
		for (int a = 0; a < m; a++)
		{
		    if (s2 == "cat and rabbit")
		    {
			d++; // false
		    }
		    if (s2 == "cat and dog")
		    {
			d--; // true
		    }
		}
	    }
	    // 7.
	    // Write results.
	    long t3 = Environment.TickCount;
	    Console.Write((t2 - t1));
	    Console.WriteLine("," + (t3 - t2));
	}
	Console.ReadLine();
    }
}

Results. The tests were repeated 10 times and averaged. You can see benchmark results at the top. The string.Intern version is much faster when the strings being compared happen to be equal. When they are not, the performance is the same.

string.Intern method performance test results

No string.Intern:   1540 ms
With string.Intern:  736 ms [faster]

Tips

Programming tip

The string.Intern method only speeds things up when two strings are equal. This only happens when an interned string is compared with another. Use string.Intern when the following characteristics are true.

More tips. Use string.Intern at startup. Usually using string.Intern is best at the start of your program. Use Intern when literals are compared. Use string.Intern only when two strings in the pool are compared. So only use it when two Interned strings are compared, or one on Interned is compared with a literal. Use if performance is critical. I use string.Intern in code that handles tens of thousands of matches every day. The performance gain is likely tiny but measurable.

Warning: Never use string.Intern without benchmarking unless you are very experienced with it. Do not use it when you have fewer than tens of thousands of matches. Do not use it if the string comparisons will rarely be true.

Summary

The C# programming language

We looked at the string.Intern method in the C# programming language. This method can make string comparisons four or more times faster. Only use it in specific situations. Always benchmark when using it. The string pool is a huge optimization and string.Intern lets us developers tap into it. You can find more information on the topic of string literals.

String Literal IsInterned String Type
.NET