설치 .NET 4.0 런타임은.NET 2.0 런타임보다 느립니다.




넷프레임워크 (4)

우리에게는 같은 문제가 있습니다. .NET 3.5 (VS2008)에서 .NET 4 (VS2010)로 wpf 프로젝트를 변환 한 후 GUI는 응답 속도가 느립니다 (모든 클릭에 대해 거의 1 초 지연).

Visual Studio 2010은 VS2010에서 제거 할 때 더 많은 리소스를 낭비하고 모든 것이 느려지므로 조사를 한 결과 빌드 된 프로젝트를 .exe로 실행하면 다시 실행됩니다.

내 프로젝트를 .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 자체 내에서 다른 대상 프레임 워크간에?


나는 벤치 마크에 결함이 있다는데 동의한다.

  • 너무 짧습니다.
  • 이전에 지적했듯이 x86 / x64의 다른 JIT는 루프를 다르게 최적화 할 가능성이 큽니다.
  • 정말 빠른 레지스터 액세스 JITted 가능성 스택 변수를 테스트합니다. 보다 실제적인 벤치 마크는 최소한 주소 공간으로의 액세스를 이동해야합니다.

추가 시간의 대부분은 x86 경우에 WoW 계층에 의해 취해질 가능성이 큽니다. 그러나 x64 프로세스의 고유 한 비효율은 실제로 메모리에 접촉하는 더 긴 벤치 마크에서 와우 레이어의 오버 헤드보다 중요 할 수 있습니다. 실제로, 벤치 마크가 (힙에 객체를 생성하고 접근하여) 메모리에 액세스한다면, WoW 레이어 포인터 최적화 이점을 볼 수 있습니다.


나는 당신의 벤치 마크에 결함이 있다고 생각합니다. 샘플 프로그램에 대한 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 VS 2010 빌드에 다른 JIT 컴파일러가 사용됩니다. JIT 컴파일러가 별도로 개발되므로 다른 결과가 발생할 수 있습니다.


나는 그것을 얻었다 고 생각한다.

64 비트 시스템에서 실행중인 경우 빌드가 "x86"이 아닌 "모든 CPU"로 설정되어 있는지 확인하십시오. 그렇게하면 내 컴퓨터에서 문제가 해결되었습니다.

VS2010에서 새로운 프로젝트의 기본값이 "Any CPU"에서 "x86"으로 변경되었습니다. 이것은 64 비트 시스템에서 편집 및 계속 작업을 기본적으로 수행한다고 생각합니다 (x86 만 지원하므로).

64 비트 시스템에서 x86 프로세스를 실행하는 것은 명백히 다소 차선책입니다.

편집 : Dustin의 의견에 따르면, x64보다는 x86을 사용하면 메모리를보다 효율적으로 사용할 수 있다는 측면에서 성능 이점이 있습니다 (짧은 참조).

또한 Dustin과 이메일로도 의견을 교환했으며 그 이유는 다음과 같습니다.

FWIW, 기본 대상 플랫폼이 ENC를 지원하도록 변경되지 않았습니다. 우리는 이미 x64에서 깨진 ENC를 2 회 출시했습니다. 그래서 ENC 자체가 전환 할 강력한 이유는 아닙니다. 우리가 전환 한 주된 이유는 (특별한 순서가 없음) 다음과 같습니다 :

  • IntelliTrace는 x64에서 지원되지 않습니다. 따라서 가장 멋진 새로운 기능 중 하나가 모든 CPU 프로젝트에서 x64 Windows에서 작동하지 않습니다.

  • x64 EXE는 x64 Windows에서 x86 EXE보다 느리게 실행됩니다. 따라서 x86 디버그, x64 릴리스에 대한 아이디어는 릴리스의 "최적화 된"빌드가 실제로 성능이 저하 될 수 있음을 의미합니다.

  • 고객이 응용 프로그램을 배포하고 컴퓨터에서 작동하더라도 응용 프로그램이 작동하지 않는 것으로 확인되면 고객이 불만을 제기합니다. 이들은 종종 P / Invoke를 중심으로 이루어졌지만 응용 프로그램에서 다른 비트로 실행될 때 중단 될 수있는 많은 다른 가정이있었습니다.

위의 이유는 모든 CPU가 아무런 이점도 가져 오지 않는다는 것을 의미합니다 (예 : EXE가 x86에서 계속 실행될 수 있기 때문에 확장 된 주소 공간을 실제로 활용할 수 없음).

릭 바이어스 (Rick Byers)는이 주제에 대해 훌륭한 글을 올리고 here .







benchmarking