HomeSearch

C# string.Intern and IsInterned

Use the string.Intern method. Benchmark the string intern pool and test IsInterned.

Intern.

The string.Intern method optimizes string memory and performance. It allows you to put strings in the runtime's shared string pool.

Notes, usage.

We call IsInterned to see if an interned string exists. Most programs will not use Intern or IsInterned. But it helps to know what they are.

An example.

The Intern static method can improve performance of string comparisons by more than two times. Intern puts strings in a common string pool maintained by the .NET runtime.Static

Note: The string pool is an optimization mainly for string literals, which are strings that you place directly in your code.

Literals: String literals are surrounded by quotes. They are constant and immutable—meaning you can't change them.

String Literal
C# program that uses string.Intern class Program { static void Main() { // Regular string literal. string s1 = "I'm a string literal."; // Const string literal. const string s2 = "I'm also a string literal."; // Verbatim string literal. string s3 = @"I'm a string literal with the verbatim syntax."; } }

Example 2.

You cannot change string literals. However, you can reassign the variable that points to them. This changes the reference, not the value.

Here: In this program, we modify a string reference only. The actual data, the literals, are left alone.

C# program that reassigns string literals class Program { static void Main() { string s = "I'm a string literal."; s = "I'm another literal."; } }

Example 3.

Intern takes a string you build up at runtime and basically turns it into a string literal. This makes comparisons much faster.

Tip: Microsoft says that the Intern method uses the intern pool to search for a string equal to the value.

And: If the string does not exist, a reference to str is added to the intern pool, then that reference is returned.

String.Intern: Microsoft Docs
C# program that in terns string 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); } }

Equals.

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

Next: The Equals method is how the == operator is implemented in the .NET Framework. The first part tests the references for equality.

Also: EqualsHelper compares all the characters in a loop and is slower. It is called if the other conditions do not short-circuit.

Implementation of string.Equals: C# public static bool Equals(string a, string b) { return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b))); }

A benchmark.

String.Intern improves performance by more than four times when the string comparison is always true. For the example, one comparison is false and one is true.True, False

Next: The tests were repeated 10 times and averaged. The benchmark results come after the code.

Result: The string.Intern version is faster when the strings are equal. When they are not, the performance is the same.

C# program that compares performance 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(); } } Output No string.Intern: 1540 ms With string.Intern: 736 ms [faster]

Discussion.

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

IsInterned.

With string.IsInterned, you can test whether a string is present in the internal table, without adding it if it is not. It receives a string reference and returns one too.

Info: If the internal string is found, that reference is returned. If no internal string is present, a null reference is returned.

Null

First: A string literal is tested. This reveals that string literals are always present in the intern table.

And: On the other hand, a dynamically constructed string is not present in the intern table.

Null: IsInterned will return null in this case. It will not add the string to the intern table.

C# program that uses IsInterned method using System; class Program { static void Main() { // See if a string literal is interned. string value1 = "cat"; string value2 = string.IsInterned(value1); Console.WriteLine(value2); // See if a dynamically constructed string is interned. string value3 = "cat" + 1.ToString(); string value4 = string.IsInterned(value3); Console.WriteLine(value4 == null); } } Output cat True

Usage.

In most programs, you do not need to use Intern or IsInterned. But if you use the intern table in other places, you might want to use the string.IsInterned method.

A summary.

String.Intern and IsInterned act on the string intern pool. Intern can make string comparisons four or more times faster. The string pool is an important optimization.
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.