Given: a base64 string
When: Foo
is called
Then: Foo
returns the input string with the following character replacements ('A' => '_', 'B' => '-', 'C' => '+')
and does it as fast as possible
I compared several algorithms to determine which version of Foo
is faster. The results point towards plain-old string.Replace
, which is quite surprising. I would have expected the Regex to take an initial hit for compiling, but then blaze through and outperform string.Replace
which creates three copies of the string per invocation of Foo
.
I'd like to check if anybody else can confirm these findings or come up with an explanation of why the winner outperformed the rest.
I ran Foo
100k times with these algorithms and the result is the TimeSpan
, measured with StopWatch
on a debug build, after finishing execution:
00:00:00.0500790 <=== string.Replace [1]
00:00:00.0699696 <=== StringBuilder.Append [2]
00:00:00.0988960 <=== StringBuilder.Replace [3]
00:00:00.7440135 <=== Regex [4]
[1]:
Foo(string input)
{
return input.Replace("A", "_").Replace("B", "-").Replace("C", "+");
}
[2]:
Foo(string input)
{
var sb = new StringBuilder(input.Length);
foreach (var x in input)
{
if (x == 'A')
{
sb.Append('_');
}
else if (x == 'B')
{
sb.Append('-');
}
else if (x == 'C')
{
sb.Append('+');
}
else
{
sb.Append(x);
}
}
return sb.ToString();
}
[3]:
Foo(string input)
{
return new StringBuilder(input, input.Length).Replace("A", "_").Replace("B", "-").Replace("C", "+").ToString()
}
[4]:
static readonly Regex charsRegex = new Regex(@"[ABC]", RegexOptions.Compiled);
Foo(string input)
{
charsRegex.Replace(input, delegate (Match m)
{
var value = m.Value;
if (value == "A")
{
return "_";
}
else if (value == "B")
{
return "-";
}
else if (value == "C")
{
return "+";
}
return value;
});
}