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

发布于 2024-09-02 19:34:52 字数 1220 浏览 3 评论 0原文

在我将项目升级到 .NET 4.0(使用 VS2010)后,我意识到它们的运行速度比在 .NET 2.0(VS2008)中慢。所以我决定在 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 本身内部的不同目标框架之间?

After I upgraded my projects to .NET 4.0 (With VS2010) I realized than they run slower than they were in .NET 2.0 (VS2008). So i decided to benchmark a simple console application in both VS2008 & VS2010 with various Target Frameworks:

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);
            }
        }
    }
}

Here is the results:

  • VS2008
    • Target Framework 2.0: ~0.25 seconds
    • Target Framework 3.0: ~0.25 seconds
    • Target Framework 3.5: ~0.25 seconds
  • VS2010
    • Target Framework 2.0: ~3.8 seconds
    • Target Framework 3.0: ~3.8 seconds
    • Target Framework 3.5: ~1.51 seconds
    • Target Framework 3.5 Client Profile: ~3.8 seconds
    • Target Framework 4.0: ~1.01 seconds
    • Target Framework 4.0 Client Profile: ~1.01 seconds

My initial conclusion is obviously that programs compiled with VS2008 working faster than programs compiled with VS2010.

Can anyone explain those performance changes between VS2008 and VS2010? and between different Target Frameworks inside VS2010 itself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

漆黑的白昼 2024-09-09 19:34:52

我想我已经明白了。

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

VS2010 中新项目的默认设置从“任何 CPU”更改为“x86” - 我相信这是为了使“编辑”和“继续”默认在 64 位计算机上工作(因为它仅支持 x86)。

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

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

我还通过电子邮件与达斯汀联系了此事,他列举了以下原因:

FWIW,默认目标平台
未更改以支持 ENC。我们有
已发货 ENC 在 x64 上损坏
2 次发布。所以就其本身而言,ENC 并不是
确实是一个令人信服的切换理由。
我们更换的主要原因(没有
特定顺序)是:

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

  • x64 EXE 在 x64 Windows 上的运行速度比 x86 EXE 慢。所以,x86的想法
    调试,x64 版本意味着
    发布中的“优化”构建将
    实际上表现更差。

  • 部署应用程序时发现客户投诉
    不起作用,尽管它有效
    他们的机器。这些经常出现在
    P/Invoke,但还有许多其他
    可以做出的假设
    运行时可能会中断的应用程序
    具有不同的位数。

以上原因加上
事实上,Any CPU 不会带来
好处(即你实际上不能接受
扩展地址的优势
空间,因为 EXE 可能仍然运行在
x86)是默认的原因
被切换了。

瑞克拜尔斯有一个
关于这个主题的优秀帖子
这里

I think I've got it.

If you're running on a 64 bit machine, make sure the build is set to "Any CPU" rather than "x86". Doing that fixed the issue on my machine.

The default for new projects changed in VS2010 from "Any CPU" to "x86" - I believe this was to make Edit and Continue work by default on 64 bit machines (as it only supports x86).

Running an x86 process on a 64 bit machine is obviously somewhat suboptimal.

EDIT: As per Dustin's comments, running x86 rather than x64 can have performance advantages in terms of more efficient use of memory (shorter references).

I also corresponded with Dustin about this by email, and he included these reasons:

FWIW, the default target platform
wasn’t changed to support ENC. We had
already shipped ENC broken on x64 for
2 releases. So by itself, ENC wasn’t
really a compelling reason to switch.
The primary reasons we switched (in no
particular order) were:

  • IntelliTrace is not supported on x64. So, one of the coolest new
    features won’t work on x64 Windows for
    Any CPU projects.

  • x64 EXEs run slower on x64 Windows than x86 EXEs do. So, the idea of x86
    debug, x64 release would mean that
    “optimized” builds in Release would
    actually perform worse.

  • Customer complaints when deploying an application and finding that it
    doesn’t work, even though it worked on
    their machine. These were often around
    P/Invoke, but there any many other
    assumptions that can be made in an
    application that can break when run
    with different bitness.

The above reasons coupled with the
fact that an Any CPU brings no
benefits (i.e. you can’t actually take
advantage of the expanded address
space because the EXE may still run on
x86) was the reason that the default
was switched.

Rick Byers has an
excellent post on this topic
here.

清欢 2024-09-09 19:34:52

我相信你的基准是有缺陷的。示例程序的 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 位系统,这将导致 VS 2008 与 VS 2010 构建使用不同的 JIT 编译器。由于 JIT 编译器是单独开发的,这可能会导致不同的结果。

I believe your benchmark is flawed. The IL code from VS 2008 and VS 2010 for your sample program is identical in release mode (VS 2008 targeting .NET 2.0 and VS 2010 targeting .NET 4.0 with default settings). Therefore you should not see a difference in timings between VS 2008 and VS 2010. Both compilers emit the following code:

.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

One thing that might be different is the platform target. VS 2010 uses x86 as the default platform target whereas VS 2008 uses AnyCPU. If you are on a 64-bit system this will result in different JIT compilers being used for the VS 2008 vs. VS 2010 builds. This might lead to different results as the JIT compilers are developed separately.

傲世九天 2024-09-09 19:34:52

我同意该基准是有缺陷的。

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

在 x86 情况下,大部分额外时间可能由 WoW 层占用。然而,在实际涉及内存的较长基准测试中,x64 进程固有的低效率很可能会超过 WoW 层的开销。事实上,如果基准测试是访问内存(通过创建和访问堆上的对象),您就会看到 WoW 层指针优化的好处。

I agree that the benchmark is a flawed.

  • It is too short.
  • As pointed out earlier, the different JITs for x86/x64 are likely optimizing the loop differently.
  • It really only tests stack variables which are likely JITted to fast register access. A more real world benchmark should at least move access the address space.

Most of the additional time is likely taken by the WoW layer in the x86 cases. However, the inherent inefficiencies of an x64 process would very likely outweigh the overhead of the WoW layer in a longer benchmark that actually touches memory. In fact, if the benchmark were to access memory (by creating and accessing objects on the heap), you'd see the WoW layers pointer optimization benefits.

暗喜 2024-09-09 19:34:52

我们有同样的问题。将 wpf 项目从 .NET 3.5 (VS2008) 转换为 .NET 4 (VS2010) 后,GUI 的响应速度大大降低(每次单击几乎延迟 1 秒)。

经过一番调查,我们发现,这是因为 Visual Studio 2010 占用了更多的资源,并且当我们从 VS2010 调试时,一切都变慢了。当我们将构建的项目作为 .exe 运行时,它再次运行得很快。

We have the same problem. After converting wpf project from .NET 3.5 (VS2008) to .NET 4 (VS2010), the GUI is much less responsive (almost 1 sec delay for every click).

After some investigation, we figured, it is because Visual Studio 2010 sucks much more resources and everything is slower when we degub from VS2010. When we run the builded project as .exe it runs fast again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文