代码之家  ›  专栏  ›  技术社区  ›  DxCK

.NET 4.0运行时是否比.NET 2.0运行时慢?

  •  22
  • DxCK  · 技术社区  · 16 年前

    在我将项目升级到.NET 4.0(带有VS2010)之后,我意识到它们的运行速度比.NET 2.0(VS2008)慢。因此,我决定在VS2008和VS2010中用各种目标框架对一个简单的控制台应用程序进行基准测试:

    using System;
    using System.Diagnostics;
    using System.Reflection;
    
    namespace RuntimePerfTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine(Assembly.GetCallingAssembly().ImageRuntimeVersion);
                Stopwatch sw = new Stopwatch();
    
                while (true)
                {
                    sw.Reset();
                    sw.Start();
    
                    for (int i = 0; i < 1000000000; i++)
                    {
    
                    }
    
                    TimeSpan elapsed = sw.Elapsed;
                    Console.WriteLine(elapsed);
                }
            }
        }
    }
    

    结果如下:

    • VS2008
      • 目标框架2.0:~0.25秒
      • 目标框架3.0:~0.25秒
      • 目标框架3.5:~0.25秒
    • VS2010
      • 目标框架2.0:~3.8秒
      • 目标框架3.0:~3.8秒
      • 目标框架3.5:~1.51秒
      • 目标框架3.5客户端配置文件:~3.8秒
      • 目标框架4.0:~1.01秒
      • 目标框架4.0客户端配置文件:~1.01秒

    我的初步结论是,用VS2008编译的程序比用VS2010编译的程序工作得更快。

    有人能解释一下VS2008和VS2010之间的性能变化吗?在VS2010内部不同的目标框架之间?

    4 回复  |  直到 16 年前
        1
  •  27
  •   Jon Skeet    16 年前

    我想我明白了。

    如果您在64位计算机上运行,请确保构建设置为“任意CPU”,而不是“x86”。这样就解决了我机器上的问题。

    VS2010中新项目的默认值从“any cpu”更改为“x86”-我认为这是为了使编辑和继续在默认情况下在64位计算机上工作(因为它只支持x86)。

    在64位计算机上运行x86进程显然有些次优。

    编辑:根据达斯汀的评论,运行x86而不是X64在更高效地使用内存(更短的引用)方面具有性能优势。

    我也通过电子邮件与达斯汀通信,他包括以下原因:

    fwiw,默认目标平台 _秷秷没有更改为支持ENC。 已发货的Enc在x64上损坏,用于 2版本。因此,Enc本身就是 真的是一个令人信服的理由来改变。 我们调换的主要原因(不 具体顺序)是:

    • x64不支持IntelliTrace。所以,最酷的新产品之一 在X64 Windows上无法使用的功能 任何CPU项目。

    • 在x64 Windows上,x64 Exe的运行速度比x86 Exe慢。所以,x86的想法 调试,x64版本意味着 _156;优化_157;版本将 实际上表现更差。

    • 客户在部署应用程序并发现 不起作用,即使它起作用 他们的机器。它们经常在附近 P/Invoke,但是还有很多 可以在 运行时可能中断的应用程序 不同的咬度。

    以上原因加上 任何CPU都不会带来 好处(也就是说,你可以 扩展地址的优势 空间,因为exe可能仍在运行 x86)是默认 被切换。

    Rick Byers有一个 关于这个话题的优秀文章 here .

        2
  •  8
  •   Dirk Vollmar    16 年前

    我相信你的基准是有缺陷的。在发布模式下,来自于Vs2008和Vs2010的示例程序的IL代码是相同的(使用默认设置时,针对.NET 2.0和Vs2010针对.NET 4.0)。因此,与2008年和2010年相比,您不应该看到时间上的差异。两个编译器都会发出以下代码:

    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // Code size       69 (0x45)
      .maxstack  2
      .locals init ([0] class [System]System.Diagnostics.Stopwatch sw,
               [1] int32 i,
               [2] valuetype [mscorlib]System.TimeSpan elapsed)
      IL_0000:  call       class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetCallingAssembly()
      IL_0005:  callvirt   instance string [mscorlib]System.Reflection.Assembly::get_ImageRuntimeVersion()
      IL_000a:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_000f:  newobj     instance void [System]System.Diagnostics.Stopwatch::.ctor()
      IL_0014:  stloc.0
      IL_0015:  ldloc.0
      IL_0016:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Reset()
      IL_001b:  ldloc.0
      IL_001c:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Start()
      IL_0021:  ldc.i4.0
      IL_0022:  stloc.1
      IL_0023:  br.s       IL_0029
      IL_0025:  ldloc.1
      IL_0026:  ldc.i4.1
      IL_0027:  add
      IL_0028:  stloc.1
      IL_0029:  ldloc.1
      IL_002a:  ldc.i4     0x3b9aca00
      IL_002f:  blt.s      IL_0025
      IL_0031:  ldloc.0
      IL_0032:  callvirt   instance valuetype [mscorlib]System.TimeSpan [System]System.Diagnostics.Stopwatch::get_Elapsed()
      IL_0037:  stloc.2
      IL_0038:  ldloc.2
      IL_0039:  box        [mscorlib]System.TimeSpan
      IL_003e:  call       void [mscorlib]System.Console::WriteLine(object)
      IL_0043:  br.s       IL_0015
    } // end of method Program::Main
    

    有一点可能不同,那就是平台目标。VS 2010使用 x86 作为默认平台目标,而vs 2008使用 AnyCPU . 如果您使用的是64位系统,这将导致不同的JIT编译器被用于vs.2008和vs.2010版本。这可能导致不同的结果,因为JIT编译器是单独开发的。

        3
  •  5
  •   Dustin Campbell    16 年前

    我同意基准是有缺陷的。

    • 它太短了。
    • 如前所述,x86/x64的不同JIT可能会以不同的方式优化循环。
    • 它实际上只测试堆栈变量,这些变量可能会被抖动以快速访问寄存器。一个更真实的基准应该至少移动访问地址空间。

    在x86情况下,大多数额外的时间可能是由wow层花费的。然而,X64进程固有的低效率很可能会超过wow层在实际触及内存的较长基准中的开销。事实上,如果基准是访问内存(通过在堆上创建和访问对象),那么您将看到wow层指针优化的好处。

        4
  •  0
  •   urza    16 年前

    我们也有同样的问题。在将WPF项目从.NET 3.5(VS2008)转换为.NET 4(VS2010)之后,GUI的响应速度要低得多(每次单击都会延迟1秒)。

    经过一些调查,我们发现,这是因为Visual Studio 2010占用了更多的资源,当我们从VS2010降级时,一切都变慢了。当我们以.exe的形式运行构建的项目时,它再次快速运行。