C# int.Parse Optimization

Int keyword

An optimized int.Parse method reduces computational complexity. It uses a for-loop on the characters in a string. It maintains the running total as it proceeds through the characters. It fails on nontrivial number strings.

Note:Faster implementations are possible for parsing ints. They are not all feature-equivalent.

Int

Example

To start, we optimize some kinds of lower-level code such as parsing routines. You can use a simple algorithm to convert an ASCII string to an integer value, in a way that is far faster than int.Parse.

int.Parse
Example unsafe parsing code: C#

using System;

class Program
{
    public static int IntParseFast(string value)
    {
	int result = 0;
	for (int i = 0; i < value.Length; i++)
	{
	    char letter = value[i];
	    result = 10 * result + (letter - 48);
	}
	return result;
    }

    static void Main()
    {
	const string s = "400";

	// A. Control method from framework.
	int i = int.Parse(s);
	Console.WriteLine(i);

	// B. Control method from framework.
	ushort i2 = ushort.Parse(s);
	Console.WriteLine(i2);

	// C. Use custom method.
	int i3 = IntParseFast(s);
	Console.WriteLine(i3);

	// D. Use custom method.
	ushort i4 = (ushort)IntParseFast(s);
	Console.WriteLine(i4);
    }
}

Output

400
400
400
400
Copyright

The method uses a classic C operation to convert a character like '1' to the integer 1. This works because ASCII characters are stored in different positions than the numbers equivalent to them, but in the same order.

Tip:The earlier a digit occurs, the more times it must be multiplied by 10 to correctly parse the number.

As we read the string from the left to the right, the current digit is one tenth of the previous one. We can multiply the previous number by 10 to satisfy this condition. The 48 we use simply shifts ASCII digits to ints.

Performance

Squares

Why is the custom method faster? Think of how many different things int.Parse must deal with: negative numbers, decimals, null characters, letters, line breaks, spaces, colons and different locales.

And:We don't need all that every time. We just need to parse a series of characters and store it in an int or ushort.

int.Parse optimization

int.Parse("400")     123.07 ns
IntParseFast("400")    2.87 ns

Unsafe code:The first versions of this article used the unsafe context. In my testing the unsafe code makes this algorithm slower.

Unsafe

Therefore:There is really no reason to use unsafe code here. The unsafe implementation has been removed.

Reduce locals

Char type

I revisited this method after learning more about the intermediate language. What I realized is that reducing the number of local variables could improve performance. This means eliminating the char variable and simply using value[i].

Result:This improves performance about 10% further in my tests. This is a worthwhile change.

Updated IntParseFast, reduces locals: C#

public static int IntParseFast(string value)
{
    int result = 0;
    for (int i = 0; i < value.Length; i++)
    {
	result = 10 * result + (value[i] - 48);
    }
    return result;
}

Performance results

10.51 ns [3 calls with char local]
 9.67 ns [3 calls (updated version)]

Summary

Framework: NET

If you are desperate enough for performance, it is possible to provide alternative implementations for methods such as int.Parse. This can yield significant performance improvements in some programs.


C#: String