string.IndexOf性能

Gho*_*der 6 .net c# performance

这个简单的c#代码用于在HTML中查找脚本块,需要0.5秒才能在74K字符串上运行,其中只有9个脚本块.这是2.8Ghz i7 CPU上未发布的二进制文件.我通过此代码进行了多次运行,以确保性能不受JIT的阻碍.它不是.

这是VS2010 .NET 4.0 Client Profile.64位

为什么这么慢?

                int[] _exclStart = new int[100];
                int[] _exclStop = new int[100];
                int _excl = 0;
                for (int f = input.IndexOf("<script", 0); f != -1; )
                {
                    _exclStart[_excl] = f;
                    f = input.IndexOf("</script", f + 8);
                    if (f == -1)
                    {
                        _exclStop[_excl] = input.Length;
                        break;
                    }
                    _exclStop[_excl] = f;
                    f = input.IndexOf("<script", f + 8);
                    ++_excl;
                }
Run Code Online (Sandbox Code Playgroud)

Sep*_*eph 18

我使用此页面上的源代码作为示例,然后我将内容复制8次,导致页面长度为334,312字节.使用StringComparision.Ordinal会产生巨大的性能差异.

string newInput = string.Format("{0}{0}{0}{0}{0}{0}{0}{0}", input.Trim().ToLower());
//string newInput = input.Trim().ToLower();

System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
int[] _exclStart = new int[100];
int[] _exclStop = new int[100];
int _excl = 0;
for (int f = newInput.IndexOf("<script", 0, StringComparison.Ordinal); f != -1; )
{
    _exclStart[_excl] = f;
    f = newInput.IndexOf("</script", f + 8, StringComparison.Ordinal);
    if (f == -1)
    {
        _exclStop[_excl] = newInput.Length;
        break;
    }
    _exclStop[_excl] = f;
    f = newInput.IndexOf("<script", f + 8, StringComparison.Ordinal);
    ++_excl;
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
Run Code Online (Sandbox Code Playgroud)

运行5次会产生几乎相同的结果(循环时序没有显着变化,因此对于这个简单的代码,JIT几乎没有时间来编译它)

使用原始代码输出(以毫秒为单位):

10.2786
11.4671
11.1066
10.6537
10.0723
Run Code Online (Sandbox Code Playgroud)

使用上面的代码输出(以毫秒为单位):

0.3055
0.2953
0.2972
0.3112
0.3347
Run Code Online (Sandbox Code Playgroud)

请注意,我的测试结果大约是0.010秒(原始代码)和0.0003秒(对于序数代码).这意味着除了这个代码之外你还有其他错误.

如果如你所说,使用StringComparison.Ordinal对你的表现没有任何作用那么这意味着要么你使用不正确的计时器来计算你的表现,要么你在读取你的input价值时会有很大的开销,比如再次从流中读取你没有意识到的.

在使用.NET 4 Client Profile在3GHz i5上运行的Windows 7 x64下测试.

建议:

  1. 使用 StringComparison.Ordinal
  2. 确保你习惯System.Diagnostics.Stopwatch性能
  3. 声明一个局部变量的input,而不是使用外部值的函数(例如:string newInput = input.Trim().ToLower();)

我再次强调,使用与您提供的完全相同的代码,测试数据的速度明显提高了4倍,我的速度提高了50倍.这意味着我的测试运行速度比你的快200倍,这是任何人都不会想到的,因为我们都运行相同的环境,只有i5(me)和i7(你).


Mat*_*hen 5

您使用的 IndexOf 重载是文化敏感的,这会影响性能。相反,使用:

input.IndexOf("<script", 0, StringComparison.Ordinal); 
Run Code Online (Sandbox Code Playgroud)