Dot Net Perls
C#

Char Array Performance

by Sam Allen

Problem

Build up an array of chars to optimize performance and simplify code. You know the maximum numbers of characters. You can replace your StringBuilder for char-appending operations.

Solution: C#

Here we append characters one-by-one to an array. We will use the char[] data type. Chars in C# are 2-bytes, which is larger than in C and C++, but still very small. Here is some example code where I replace StringBuilder with char[].

/// <summary>
/// Example method of how we can copy and build up a string from char values
/// with a StringBuilder. This is the slow version.
/// </summary>
public static string AppendStringBuilder()
{
    // Declare new builder and append to it 100 times.
    StringBuilder builder = new StringBuilder(100);
    for (int i = 0; i < 100; i++)
    {
        builder.Append('a');
    }
    return builder.ToString();
}

/// <summary>
/// Example method of how we can copy to an array and then return
/// a new string with its constructor. This is faster.
/// </summary>
public static string AppendChar()
{
    // Use a new char array.
    char[] buffer = new char[100];
    for (int i = 0; i < 100; i++)
    {
        buffer[i] = 'a';
    }
    return new string(buffer);
}

Why is char[] faster?

Because it doesn't have as many features. StringBuilder can deal with tons of stuff and has many methods. It is very easy to use and a great optimization, but it is far slower in simple cases.

Does this help in real programs?

Yes. I used this approach when using GZipStream compression in C#. I also used it as an improvement in the alphanumeric sorting algorithm.

Example: char[] array

This next example declares a |space1| char buffer, and then builds up characters into it. We know the maximum number of characters. I have encountered many algorithms like this one, so this is not a rare example.

// A buffer of char[] instead of a StringBuilder.
char[] space1 = new char[len1];
int loc1 = 0;
do
{
    space1[loc1++] = ch1;
    marker1++;

    if (marker1 < len1)
    {
        ch1 = s1[marker1];
    }
    else
    {
        break;
    }
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

// Note how we make a string using a constructor on string
// that receives the char[] buffer.
string str1 = new string(space1);

How fast are they?

They are both fast, but to different degrees. Avoiding StringBuilder and using char buffers has a big performance advantage. The first image shows the theory code performance.

Algorithm StringBuilder object (time in ms) char[] buffer (time in ms)
Alphanumeric sorting 6708 4727
Theory code 1804 255

What's the point?

The char array code forces me to have more "coding discipline." It is more exact if you can enforce the constraints of char arrays. StringBuilder could have extra chars appended, but the char array wouldn't allow that.

Summary

StringBuilder is fast and very useful many times, but using char[] arrays is better if you know in advance the maximum number of characters. Using an array may also encourage higher-quality code.

© 2008 Sam Allen. All rights reserved.

Ads by The Lounge