2010-05-19 29 views
22

Sau khi tôi nâng cấp các dự án của mình lên .NET 4.0 (Với VS2010), tôi nhận ra rằng chúng chạy chậm hơn so với .NET 2.0 (VS2008). Vì vậy, tôi đã quyết định điểm chuẩn một ứng dụng giao diện điều khiển đơn giản trong cả VS2008 & VS2010 với Khung Target khác nhau:.NET 4.0 Runtime có chạy chậm hơn .NET 2.0 Runtime không?

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

Dưới đây là kết quả:

  • VS2008
    • Target Framework 2.0: ~ 0,25 giây
    • Khung mục tiêu 3.0: ~ 0.25 giây
    • Khung mục tiêu 3.5: ~ 0.25 giây
  • VS2010
    • Target Framework 2.0: ~ 3,8 giây
    • Target Framework 3.0: ~ 3,8 giây
    • Target Framework 3.5: ~ 1,51 giây
    • Target Framework 3.5 Client Profile: ~ 3.8 giây
    • Khung mục tiêu 4.0: ~ 1.01 giây
    • Khung mục tiêu 4.0 Hồ sơ khách hàng: ~ 1.01 giây

Kết luận ban đầu của tôi rõ ràng là các chương trình biên dịch với VS2008 hoạt động nhanh hơn các chương trình được biên dịch với VS2010.

Có ai có thể giải thích những thay đổi hiệu suất đó giữa VS2008 và VS2010 không? và giữa các Khung mục tiêu khác nhau bên trong VS2010?

+6

Bạn có đang chạy các chương trình này thông qua trình gỡ lỗi trong Visual studio hoặc chạy các ứng dụng ở chế độ phát hành không? –

+2

Bạn đã thử nghiệm một vài lần chạy để giảm thiểu các ảnh hưởng bên ngoài? Khi nó đứng, kết quả cũng có thể là do cơ hội một mình. Mặc dù nó * trông * kết luận, một lần chạy duy nhất sẽ mang lại gần như * không * ý nghĩa trong bài kiểm tra này. –

+0

Bạn đã thử chạy nó bên ngoài VS chưa? – eflles

Trả lời

27

Tôi nghĩ rằng tôi đã có nó.

Nếu bạn đang chạy trên máy 64 bit, hãy đảm bảo bản dựng được đặt thành "Mọi CPU" thay vì "x86". Việc đó đã khắc phục sự cố trên máy của tôi.

Mặc định cho các dự án mới thay đổi trong VS2010 từ "CPU bất kỳ" thành "x86" - tôi tin rằng điều này là để Chỉnh sửa và Tiếp tục hoạt động theo mặc định trên máy 64 bit (vì nó chỉ hỗ trợ x86).

Chạy quy trình x86 trên máy 64 bit rõ ràng là hơi tối ưu.

EDIT: Theo nhận xét của Dustin, chạy x86 thay vì x64 có thể có lợi thế về mặt hiệu suất về sử dụng bộ nhớ hiệu quả hơn (tham chiếu ngắn hơn).

Tôi cũng tương ứng với Dustin về vấn đề này qua email, và ông bao gồm những lý do sau:

FWIW, nền tảng mục tiêu mặc định không được thay đổi để hỗ trợ ENC. Chúng tôi đã có đã được giao ENC bị hỏng trên x64 cho 2 bản phát hành. Do đó, ENC không phải là thực sự là một lý do thuyết phục để chuyển đổi. Những lý do chính chúng tôi chuyển (không theo thứ tự đặc biệt ) là:

  • IntelliTrace không được hỗ trợ trên x64. Vì vậy, một trong những tính năng mới mới thú vị nhất sẽ không hoạt động trên x64 Windows cho Bất kỳ dự án CPU nào.

  • x64 EXE chạy chậm hơn trên x64 Windows hơn x86 EXE. Vì vậy, ý tưởng của x86 gỡ lỗi, bản phát hành x64 có nghĩa là các bản dựng "được tối ưu hóa" trong Bản phát hành sẽ thực sự hoạt động kém hơn.

  • Khiếu nại của khách hàng khi triển khai một ứng dụng và thấy rằng nó không hoạt động, mặc dù nó hoạt động trên máy của họ. Đây thường là khoảng P/Invoke, nhưng có nhiều giả thiết khác có thể được thực hiện trong ứng dụng có thể bị hỏng khi chạy với độ bit khác nhau.

Những lý do trên cùng với thực tế rằng một Bất kỳ CPU không đem lại lợi ích (tức là bạn có thể không thực sự mất lợi dụng mở rộng không gian địa chỉ vì EXE vẫn có thể chạy trên x86) là lý do mà mặc định đã được chuyển.

Rick Byers có bài đăng tuyệt vời về chủ đề này here.

+1

Có thể sự khác biệt là mục tiêu nền tảng? csc.exe sử dụng AnyCPU làm mặc định, trong khi VS 2010 đã thay đổi mặc định thành x86. –

+0

@ 0xA3: Đó không phải là câu trả lời cơ bản của tôi sao? –

+4

Vâng, đúng vậy, nhưng câu trả lời của bạn đã không nói điều đó khi tôi viết bình luận của tôi ;-) Tôi muốn có một sự làm mới ngay lập tức nếu ai đó cập nhật câu trả lời của họ. –

8

Tôi tin rằng điểm chuẩn của bạn là thiếu sót. Mã IL từ VS 2008 và VS 2010 cho chương trình mẫu của bạn giống hệt nhau trong chế độ phát hành (nhắm mục tiêu VS 2008 .NET 2.0 và VS 2010 nhắm mục tiêu .NET 4.0 với cài đặt mặc định). Do đó, bạn sẽ không thấy sự khác biệt về thời gian giữa VS 2008 và VS 2010. Cả hai trình biên dịch đều phát ra mã sau:

.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 

Một điều có thể khác với mục tiêu nền tảng. VS 2010 sử dụng x86 làm mục tiêu nền tảng mặc định trong khi VS 2008 sử dụng AnyCPU. Nếu bạn đang sử dụng hệ thống 64 bit, điều này sẽ dẫn đến các trình biên dịch JIT khác nhau được sử dụng cho các phiên bản VS 2008 và VS 2010. Điều này có thể dẫn đến các kết quả khác nhau khi các trình biên dịch JIT được phát triển riêng biệt.

5

Tôi đồng ý rằng điểm chuẩn là thiếu sót.

  • Quá ngắn.
  • Như đã chỉ ra trước đó, các JIT khác nhau cho x86/x64 có khả năng tối ưu hóa vòng lặp khác nhau.
  • Nó thực sự chỉ kiểm tra các biến ngăn xếp có khả năng JITted truy cập đăng ký nhanh. Một chuẩn mực thế giới thực hơn ít nhất nên di chuyển truy cập vào không gian địa chỉ.

Hầu hết thời gian bổ sung có thể được thực hiện bởi lớp WoW trong các trường hợp x86. Tuy nhiên, sự thiếu hiệu quả vốn có của một quá trình x64 rất có thể sẽ vượt quá mức phí của lớp WoW trong một điểm chuẩn dài hơn mà thực sự chạm vào bộ nhớ. Trong thực tế, nếu điểm chuẩn là để truy cập bộ nhớ (bằng cách tạo và truy cập các đối tượng trên heap), bạn sẽ thấy các lợi ích tối ưu hóa con trỏ lớp WoW.

0

Chúng tôi có cùng một vấn đề. Sau khi chuyển đổi dự án wpf từ .NET 3.5 (VS2008) sang .NET 4 (VS2010), GUI kém phản hồi hơn nhiều (gần 1 giây cho mỗi lần nhấp chuột).

Sau khi một số điều tra, chúng tôi đã tìm ra, đó là vì Visual Studio 2010 hút nhiều tài nguyên hơn và mọi thứ chậm hơn khi chúng tôi xóa khỏi VS2010. Khi chúng tôi chạy các dự án xây dựng như .exe nó chạy nhanh một lần nữa.

Các vấn đề liên quan