奇怪的表现行为

时间:2011-09-25 08:26:25

标签: c# .net string performance

我正在使用Visual Studio 2010 SP1,目标框架是2.0,平台目标:任何CPU,在Windows 7 x64 SP1下进行测试。

我遇到了奇怪的表现行为。

没有app.config,或者使用以下app.config,它会让我的程序运行缓慢(秒表显示~0.11秒)

<?xml version="1.0"?>
<configuration>
  <startup >
    <supportedRuntime version="v2.0.50727" />
  </startup>
</configuration>

以下app.config使我的程序运行速度提高了x5倍(秒表显示~0.02秒)

<?xml version="1.0"?>
<configuration>
  <startup >
    <supportedRuntime version="v4.0.30319" sku=".NETFramework,Version=v4.0" />
  </startup>
</configuration>

这是测试程序代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();

        while (true)
        {
            sw.Reset();
            sw.Start();

            for (int i = 0; i < 1000000; i++ )
            {
                "blablabla".IndexOf("ngrhotbegmhroes", StringComparison.OrdinalIgnoreCase);
            }

            Console.WriteLine(sw.Elapsed);
        }
    }
}

我坐了几个小时,无法弄清楚这里发生了什么。 你知道吗?

3 个答案:

答案 0 :(得分:15)

听起来你刚刚发现.NET 4的速度要快得多。默认情况下,您的应用程序正在运行其构建目标的框架。当你强制它使用.NET 4时,它会更快。这可能是JIT编译器的改进,它碰巧遇到了你的情况,或者它可能是一个框架改进 - 但是在新版本中某些东西更快的情况应该不会太令人惊讶。

(对于它的价值,如果我是你的话,我会增加你的计时重复次数...在.NET 4下的盒子里,每次迭代只有10ms,这真的不是很好测量。我更喜欢基准测试至少几秒钟。)

(和米奇一样,我可以确认我看到同样的效果。)

编辑:我刚刚对此进行了进一步调查,看到了一个有趣的效果......我假设我们正在调用haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase)

  • 在.NET 2上,结果大致相同,但“针”是
  • 在.NET 4上:
    • 如果needle大于haystack(根据您的示例),.NET 4比.NET 2快得多
    • 如果needlehaystack的大小相同,则.NET 4的比.NET 2慢
    • 如果needle小于haystack,则.NET 4 批次比.NET 2慢

(这是测试needle的第一个字符永远不会出现在haystack,顺便说一句。

答案 1 :(得分:4)

我只是通过一些调整(包括更多迭代和平均)来运行您的基准测试,并且可以确认.NET 4.0目标版本确实快了4-5倍。

所以推测IndexOf()在.NET 4.0中进行了优化

答案 2 :(得分:3)

好的,新VS11的基准测试

n = 1000000;
string haystack = "ngrhotbegmhroes";
string needle = "blablablablablablablablablangrhotbegmhrobla bla";

.NET 4.5 :  8 ms
.NET 4.0 :  8 ms
.NET 3.5 : 45 ms
.NET 2.0 : 45 ms

因此,这些初步结果证实了您的发现,新版本更快。

然而,在更大的字符串中查找短字符串更为常见:

n = 1000000; 
haystack = "blablablablablablablablablangrhotbegmhrobla bla";  
needle = "ngrhotbegmhroes";

.NET 4.5 : 1020 ms
.NET 4.0 : 1020 ms
.NET 3.5 :  155 ms
.NET 2.0 :  155 ms

用更长的干草堆(约400个字符)

.NET 4.0 : 12100 ms
.NET 2.0 :  1700 ms

这意味着最常见的使用模式会变得更糟......


发布配置中的所有测量,以及可用的客户端配置文件 使用Ctrl + F5从VS 11运行 赢得7H,Core i7 2620M