[英]Are .NET 4.0 Runtime slower than .NET 2.0 Runtime?
在我将项目升级到.NET 4.0(使用VS2010)后,我意识到它们运行速度比在.NET 2.0(VS2008)中慢。 所以我决定使用各种Target Frameworks对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编译的程序比使用VS2010编译的程序运行得更快。
任何人都可以解释VS2008和VS2010之间的性能变化吗? 在VS2010内部的不同目标框架之间?
我想我已经明白了。
如果您在64位计算机上运行,请确保将构建设置为“任何CPU”而不是“x86”。 这样做解决了我的机器上的问题。
VS2010中新项目的默认值从“任何CPU”更改为“x86” - 我相信这是为了使编辑和继续在64位计算机上默认工作(因为它只支持x86)。
在64位计算机上运行x86进程显然有些不理想。
编辑:根据Dustin的评论,运行x86而不是x64可以在更有效地使用内存(更短的引用)方面具有性能优势。
我还通过电子邮件与Dustin通信了,他包括以下原因:
FWIW,默认目标平台未更改为支持ENC。 我们已经在x64上发布了2个版本的ENC。 因此,ENC本身并不是一个令人信服的理由。 我们切换的主要原因(无特定顺序)是:
x64不支持IntelliTrace。 因此,最酷的新功能之一将不适用于任何CPU项目的x64 Windows。
x64 EXE在x64 Windows上的运行速度比x86 EXE慢。 因此,x86调试,x64版本的想法意味着Release中的“优化”版本实际上会表现更差。
客户投诉部署应用程序并发现它不起作用,即使它在他们的计算机上运行。 这些通常是围绕P / Invoke进行的,但是在应用程序中可以进行许多其他假设,这些假设在以不同的位数运行时可能会中断。
上述原因加上Any CPU没有带来任何好处(即你实际上无法利用扩展的地址空间,因为EXE可能仍然在x86上运行)是默认切换的原因。
Rick Byers在这里有一篇关于这个主题的优秀文章。
我相信你的基准是有缺陷的。 来自VS 2008和VS 2010的示例程序的IL代码在发布模式下是相同的(VS 2008针对.NET 2.0,VS 2010以.NET 4.0为目标,默认设置)。 因此,您不应该看到VS 2008和VS 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编译器是单独开发的。
我同意基准是有缺陷的。
大多数额外时间可能是x86案例中的WoW层。 但是,x64进程固有的低效率很可能会超过实际接触内存的较长基准测试中WoW层的开销。 事实上,如果基准测试是访问内存(通过创建和访问堆上的对象),您将看到WoW层指针优化的好处。
我们有同样的问题。 将wpf项目从.NET 3.5(VS2008)转换为.NET 4(VS2010)后,GUI响应速度慢得多(每次点击几乎延迟1秒)。
经过一番调查,我们发现,这是因为Visual Studio 2010吸收了更多的资源,当我们从VS2010进行debub时,一切都变慢了。 当我们以.exe运行构建的项目时,它会再次运行得很快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.