2011-01-03 40 views
5

Tôi đang thực hành các vấn đề từ MCTS Exam 70-536 Microsft .Net Framework Application Dev Foundation, và một trong những vấn đề là tạo ra hai lớp, một kiểu generic, một kiểu đối tượng vừa thực hiện cùng một điều ; trong đó một vòng lặp sử dụng lớp và lặp lại hàng nghìn lần. Và sử dụng bộ hẹn giờ, thời gian thực hiện của cả hai. Có một bài đăng khác tại số C# generics question tìm kiếm cùng một nhiệm vụ nhưng không trả lời.Generics vs Object performance

Về cơ bản, nếu trong mã của tôi, tôi chạy lớp chung trước tiên phải mất trình ghi nhật ký để xử lý. Nếu tôi chạy lớp đối tượng đầu tiên hơn lớp đối tượng sẽ mất nhiều thời gian hơn để xử lý. Toàn bộ ý tưởng là để chứng minh rằng generics hoạt động nhanh hơn.

Tôi đã sử dụng mã người dùng ban đầu để tiết kiệm thời gian cho tôi. Tôi không đặc biệt nhìn thấy bất cứ điều gì sai trái với mã và đã bối rối bởi kết quả. Có thể một số giải thích tại sao các kết quả bất thường?

Cảm ơn,

Risho

Đây là mã:

class Program 
{ 
    class Object_Sample 
    {    
     public Object_Sample() 
     { 
      Console.WriteLine("Object_Sample Class"); 
     } 

     public long getTicks() 
     { 
      return DateTime.Now.Ticks; 
     } 

     public void display(Object a) 
     { 
      Console.WriteLine("{0}", a); 
     } 
    } 

    class Generics_Samle<T> 
    {    
     public Generics_Samle() 
     { 
      Console.WriteLine("Generics_Sample Class"); 
     } 

     public long getTicks() 
     { 
      return DateTime.Now.Ticks; 
     } 

     public void display(T a) 
     { 
      Console.WriteLine("{0}", a); 
     } 
    } 

    static void Main(string[] args) 
    {    
     long ticks_initial, ticks_final, diff_generics, diff_object; 
     Object_Sample OS = new Object_Sample(); 
     Generics_Samle<int> GS = new Generics_Samle<int>(); 

     //Generic Sample 
     ticks_initial = 0; 
     ticks_final = 0; 
     ticks_initial = GS.getTicks(); 

     for (int i = 0; i < 50000; i++) 
     { 
      GS.display(i); 
     } 
     ticks_final = GS.getTicks(); 
     diff_generics = ticks_final - ticks_initial; 

     //Object Sample 
     ticks_initial = 0; 
     ticks_final = 0; 
     ticks_initial = OS.getTicks(); 

     for (int j = 0; j < 50000; j++) 
     { 
      OS.display(j); 
     } 

     ticks_final = OS.getTicks(); 
     diff_object = ticks_final - ticks_initial; 

     Console.WriteLine("\nPerformance of Generics {0}", diff_generics); 
     Console.WriteLine("Performance of Object {0}", diff_object); 

     Console.ReadKey(); 
    } 
} 
+3

Bạn nên chấp nhận câu trả lời cho câu hỏi của mình. – SLaks

+1

Bạn nên sử dụng lớp 'Đồng hồ bấm giờ '. – SLaks

+1

Bạn nên nhấp vào dấu kiểm rỗng bên cạnh câu trả lời tốt nhất cho mỗi câu hỏi của bạn để chấp nhận câu trả lời đó. – SLaks

Trả lời

5

Kiểm tra của bạn không chính xác. Dưới đây là các phương pháp của bạn:

public void display(T a) 
{ 
    Console.WriteLine("{0}", a); // Console.WriteLine(string format, params object[] args) <- boxing is performed here 
} 

public void display(Object a)// <- boxing is performed here 
{ 
    Console.WriteLine("{0}", a); 
} 

Vì vậy, trong cả hai trường hợp bạn đang sử dụng quyền anh. Nhiều hơn sẽ là nếu lớp học của bạn, ví dụ, sẽ được tính tổng các giá trị, như:

public void add(long a) 
{ 
    Total += a; 
} 

public void display(Object a)// <- boxing is performed here 
{ 
    Total += (long) a;// <- unboxing is performed here 
} 
+0

Tôi không viết mã này, tôi chỉ muốn kiểm tra những gì cuốn sách đã sugested. Trong bình luận của bạn, bạn nói rằng "màn hình hiển thị void công cộng (Object a)" được thực hiện ở đây. Bạn có thể giải thích điều đó không? Tôi không coverting ở đây bất cứ điều gì tôi? – Risho

+0

'long' là loại giá trị. Khi bạn đang truyền kiểu giá trị cho đối tượng, nó được gọi là 'boxing'. Điều đó có nghĩa là loại giá trị được bao bọc bởi 'hộp' đặc biệt, là loại tham chiếu. Tại thời điểm này. Net cần phải cấp phát bộ nhớ cho 'chiếc hộp' này và điều này không hoạt động quá nhanh. Khi bạn truyền đối tượng vào kiểu giá trị, nó được gọi là 'unboxing', giá trị được sao chép từ 'ô' sang biến của bạn. Khi bạn đang gọi phương thức với chữ ký 'phương thức (đối tượng a)' .Net thực hiện phép ẩn ngầm của 'long' thành' đối tượng' và tạo ra khoảng cách hiệu năng nào đó do quyền anh. –

+0

Vì vậy, không cần biết đối số đầu vào bạn đang sử dụng trong phương thức 'display' của bạn là gì, bởi vì trong trường hợp 'object' case boxing diễn ra trên' display' method call, và trong 'generic' trên 'Console.WriteLine' gọi phương thức - nhưng vẫn đang diễn ra. –

8

Bạn nên chạy cả hai lớp một thời gian riêng biệt trước khi thời gian đó để cho phép các Jitter để chạy.

+0

+1 Điều này nghe có vẻ như jitter với tôi là tốt. –

+0

Bạn đã kiểm tra hồ sơ của mình để xem liệu có câu trả lời có chấp nhận được không? –

+1

@Henk - Tôi nghĩ sau 13 câu hỏi ít nhất * một * câu trả lời có thể chấp nhận được. Nhưng một lần nữa, sự chấp nhận là trong con mắt của kẻ thù. –

3

tại sao nó sẽ nhanh hơn? cả hai ints phải được đóng hộp để sử dụng Console.WriteLine (string, object)

chỉnh sửa: ToString() chính nó dường như không gây ra đấm bốc http://weblogs.asp.net/ngur/archive/2003/12/16/43856.aspx

vì vậy khi bạn sử dụng Console.WriteLine (a); mà sẽ gọi Console.WriteLine (Int32) mà nên làm việc tôi đoán (tôi sẽ cần phải nhìn vào phản xạ để xác nhận điều này)

+0

Sách giáo khoa chỉ ra rằng generics nhanh hơn. – Risho

+0

chúng sẽ nhanh hơn nếu chúng ngăn chặn boxing và unboxing, nhưng đó không phải là trường hợp ở đây – Kikaimaru

+0

Tôi đang cố gắng hiểu điều này: Tôi không chuyển đổi bất kỳ ở đây, trừ khi Console.WriteLines làm, mà tôi không biết. Nếu đó là trường hợp làm thế nào để bạn hiển thị các kết quả mà không có "boxing/unboxing"? – Risho

9

Vâng, vấn đề đầu tiên tôi có thể thấy là bạn đang sử dụng đối tượng DateTime để đo thời gian trong ứng dụng của bạn (trong một khoảng thời gian rất nhỏ).

Bạn nên sử dụng lớp Stopwatch. Nó cung cấp độ chính xác tốt hơn khi cố gắng chuẩn mã.

Vấn đề thứ hai là bạn không cho phép JIT (Biên dịch Just-In-Time). Cuộc gọi đầu tiên tới mã của bạn sẽ mất nhiều thời gian hơn đơn giản chỉ vì nó phải là JIT'd. Sau đó, bạn sẽ nhận được kết quả của mình.

Tôi sẽ thực hiện một cuộc gọi đến mã của bạn trước khi bạn bắt đầu tính thời gian để bạn có thể có được ý tưởng chính xác về những gì đang xảy ra trong vòng lặp.

+1

+1 Đối với 'Đồng hồ bấm giờ' –

3
  1. mã thời gian của bạn bao gồm một Console.WriteLine(). Điều đó sẽ chiếm 99.999999% thời gian.
  2. Giả định rằng chung chung sẽ nhanh hơn trong trường hợp này là sai. Bạn có thể đã hiểu sai về nhận xét về các lớp học không chung chung.
  3. Điều này sẽ không nằm trong bài kiểm tra của anh ấy.