2008-09-18 67 views
15

Hệ thống tôi làm việc ở đây được viết trước đây .net 2.0 và không có lợi ích của generics. Nó cuối cùng đã được cập nhật lên 2.0, nhưng không có mã nào được tái cấu trúc do các ràng buộc về thời gian. Có một số nơi mà mã sử dụng ArraysLists vv để lưu trữ mọi thứ dưới dạng đối tượng.Generics vs. Array Lists

Từ quan điểm hiệu suất, mức độ quan trọng của việc thay đổi mã để sử dụng Generics? Tôi biết từ một quan điểm về mặt ngoại giao, quyền anh và unboxing, nó không hiệu quả, nhưng có bao nhiêu hiệu suất đạt được sẽ thực sự thay đổi nó? Generics là một cái gì đó để sử dụng trên cơ sở đi tiếp, hoặc nó có đủ của một sự thay đổi hiệu suất mà một nỗ lực lương tâm nên được thực hiện để cập nhật mã cũ?

Trả lời

14

Về mặt kỹ thuật hiệu suất của generics, như bạn nói, tốt hơn. Tuy nhiên, trừ khi hiệu suất là cực kỳ quan trọng VÀ bạn đã được tối ưu hóa trong các lĩnh vực khác, bạn có khả năng để có được cải thiện MUCH tốt hơn bằng cách dành thời gian của bạn ở nơi khác.

tôi sẽ đề nghị:

  • Generics sử dụng trong tương lai.
  • nếu bạn có kiểm tra đơn vị vững chắc sau đó cấu trúc lại để generics như bạn liên lạc mã
  • dành nhiều thời gian khác làm refactorings/đo rằng sẽ cải thiện đáng kể hiệu suất (cuộc gọi cơ sở dữ liệu, thay đổi cấu trúc dữ liệu, vv) chứ không phải là một vài mili giây ở đây và ở đó .

Tất nhiên có những lý do khác hơn là thực hiện thay đổi để Generics:

  • ít lỗi hơn, kể từ khi bạn có thời gian biên dịch kiểm tra các loại
  • dễ đọc hơn, bạn không cần phải cast trên tất cả các địa điểm và rõ ràng loại nào được lưu trữ trong bộ sưu tập
  • nếu bạn đang sử dụng Generics, sau đó sử dụng chúng ở mọi nơi
4

Cách duy nhất để biết chắc chắn là lập hồ sơ cho mã của bạn bằng công cụ như dotTrace.

http://www.jetbrains.com/profiler/

Có thể là boxing/unboxing là tầm thường trong ứng dụng cụ thể của bạn và sẽ không có giá trị refactoring. Về sau, bạn vẫn nên cân nhắc sử dụng Generics do sự an toàn kiểu thời gian biên dịch.

0

Lợi ích lớn nhất, bạn sẽ tìm thấy trong các giai đoạn Bảo trì. Generics dễ dàng hơn nhiều để đối phó và cập nhật, mà không cần phải đối phó với các vấn đề chuyển đổi và đúc. Nếu đây là mã mà bạn liên tục truy cập, thì bằng mọi cách hãy nỗ lực. Nếu đây là mã chưa được xúc động trong nhiều năm, tôi sẽ không thực sự bận tâm.

1

Điều đó phụ thuộc, câu trả lời hay nhất là lập hồ sơ cho mã của bạn và xem. Tôi thích AQTime nhưng một số gói tồn tại cho điều này.

Nói chung, nếu một ArrayList đang được sử dụng một LOT nó có thể có giá trị chuyển nó sang một phiên bản chung. Mặc dù vậy, rất có thể bạn thậm chí sẽ không thể đo lường sự khác biệt về hiệu suất. Boxing và unboxing là các bước bổ sung nhưng các máy tính hiện đại nhanh đến nỗi nó gần như không có sự khác biệt. Là một ArrayList thực sự chỉ là một mảng bình thường với một wrapper tốt đẹp, bạn có thể sẽ thấy hiệu suất nhiều hơn thu được từ việc lựa chọn cấu trúc dữ liệu tốt hơn (ArrayList.Remove là O (n)!) So với việc chuyển đổi thành generics.

Chỉnh sửa: Lập trình viên ngoài vòng pháp luật có một điểm tốt, bạn sẽ vẫn là đấm bốc và unboxing với generics, nó chỉ xảy ra ngầm. Tất cả mã xung quanh việc kiểm tra các ngoại lệ và các giá trị rỗng từ việc truyền và từ khóa "//as" sẽ giúp ích một chút.

0

Tính năng autoboxing/unboxing phải làm gì với Generics? Đây chỉ là vấn đề an toàn loại. Với một bộ sưu tập không chung chung, bạn được yêu cầu rõ ràng bỏ trở lại loại thực tế của đối tượng. Với generics, bạn có thể bỏ qua bước này. Tôi không nghĩ rằng có một sự khác biệt hiệu suất một cách này hay cách khác.

+2

Xem tài liệu về generics và tính hữu dụng của chúng khi sử dụng cấu trúc, và bạn sẽ thấy những gì boxing phải làm với nó. (Gợi ý: bạn không thể có được một con trỏ đối tượng đến một biến ngăn xếp) – Guvante

0

Công ty cũ của tôi thực sự coi vấn đề này. Cách tiếp cận chúng tôi thực hiện là: nếu dễ dàng tái cấu trúc lại, hãy thực hiện; nếu không (nghĩa là nó sẽ chạm vào quá nhiều lớp), hãy để nó lại sau. Nó thực sự phụ thuộc vào việc bạn có thời gian để làm điều đó hay không hoặc liệu có nhiều mục quan trọng hơn để được mã hóa hay không (tức là các tính năng bạn nên triển khai cho khách hàng).

Sau đó, một lần nữa, nếu bạn không làm việc trên một cái gì đó cho khách hàng, hãy tiếp tục và dành thời gian tái cấu trúc. Nó sẽ cải thiện khả năng đọc mã cho chính bạn.

3

Generics, cho dù Java hoặc .NET, nên được sử dụng để thiết kế và loại an toàn, không cho hiệu suất. Autoboxing khác với generics (về cơ bản là đối tượng ẩn đối với các chuyển đổi nguyên thủy), và như bạn đã đề cập, bạn KHÔNG nên sử dụng chúng thay cho nguyên thủy nếu có nhiều phép tính hoặc các phép toán khác. tạo/hủy đối tượng tiềm ẩn.

Nói chung, tôi khuyên bạn nên sử dụng trong tương lai và chỉ cập nhật mã hiện có nếu cần được dọn dẹp vì mục đích thiết kế/an toàn loại, chứ không phải hiệu suất.

0

Phụ thuộc vào số tiền có trong mã của bạn. Nếu bạn ràng buộc hoặc hiển thị danh sách lớn trong giao diện người dùng, có thể bạn sẽ thấy hiệu suất tăng cao.

Nếu ArrayList của bạn chỉ rắc ở đây và ở đó, thì có lẽ sẽ không có vấn đề gì nếu chỉ làm sạch nó, nhưng cũng sẽ không ảnh hưởng đến hiệu suất tổng thể.

Nếu bạn đang sử dụng rất nhiều ArrayLists trong suốt mã của bạn và nó sẽ là một sự thay thế lớn để thay thế chúng (cái gì đó có thể ảnh hưởng đến lịch biểu của bạn), bạn có thể áp dụng nếu bạn thay đổi nó tiếp cận.

Tuy nhiên, điều quan trọng là Generics dễ đọc hơn nhiều và ổn định hơn trên ứng dụng do việc nhập mạnh mẽ bạn nhận được từ chúng. Bạn sẽ thấy lợi ích không chỉ từ hiệu suất mà còn từ tính duy trì và ổn định mã. Nếu bạn có thể làm điều đó một cách nhanh chóng, tôi sẽ nói làm điều đó.

Nếu bạn có thể nhận được mua từ Chủ sở hữu sản phẩm, tôi khuyên bạn nên làm sạch nó. Bạn yêu mã của bạn nhiều hơn sau đó.

0

Nếu các thực thể trong ArrayLists là các loại đối tượng, bạn sẽ thu được một chút từ việc không truyền chúng đến đúng loại. Nếu chúng là kiểu giá trị (cấu trúc hoặc nguyên thủy như Int32), thì quá trình đóng gói/giải nén sẽ tăng thêm rất nhiều chi phí và các bộ sưu tập chung sẽ nhanh hơn nhiều.

Here's an MSDN article on the subject

8

Dưới đây là kết quả tôi nhận được từ một phân tích cú pháp đơn giản của một chuỗi từ một tập tin 100KB 100.000 lần. Danh sách chung (của char) mất 612.293 giây để đi 100.000 lần thông qua tệp. ArrayList mất 2.880.415 giây để đi 100.000 lần thông qua tệp. Điều này có nghĩa trong kịch bản này (vì số dặm của bạn sẽ thay đổi) Danh sách chung (của char) nhanh hơn 4,7 lần.

Đây là mã tôi chạy qua 100.000 lần:

Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run 
    Dim genList As New ArrayList 

    For Each ch As Char In strToProcess.ToCharArray 
     genList.Add(ch) 
    Next 

    Dim dummy As New System.Text.StringBuilder() 
    For i As Integer = 0 To genList.Count - 1 
     dummy.Append(genList(i)) 
    Next 

End Sub 

Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run 
    Dim genList As New List(Of Char) 

    For Each ch As Char In strToProcess.ToCharArray 
     genList.Add(ch) 
    Next 

    Dim dummy As New System.Text.StringBuilder() 
    For i As Integer = 0 To genList.Count - 1 
     dummy.Append(genList(i)) 
    Next 
End Sub 
0

Generics có hiệu suất tốt hơn đặc biệt là nếu bạn sẽ sử dụng giá trị kiểu (int, bool, struct, vv), nơi bạn sẽ đạt được hiệu suất thông báo đạt được.

  1. Sử dụng danh sách Array với các loại giá trị gây ra boxing/unboxing nếu thực hiện vài trăm lần chậm hơn đáng kể sau đó sử dụng Danh sách chung.

  2. khi lưu trữ loại giá trị làm đối tượng bạn sẽ tối đa bốn bộ nhớ thời gian cho mỗi mục. Mặc dù số tiền này sẽ không làm giảm RAM của bạn nhưng bộ nhớ cache nhỏ hơn có thể chứa ít mục hơn, có nghĩa là trong khi lặp lại một bộ sưu tập dài sẽ có nhiều bản sao từ bộ nhớ chính vào bộ nhớ cache làm chậm ứng dụng của bạn.

Tôi đã viết về here.

+1

Logic ứng dụng của bạn đã bị thiếu sót. Cụ thể, InsertItemsToList có nút stopper.Start() bị thất lạc. Nó cần phải được bên trong vòng lặp. Ngoài ra, sự khác biệt hiệu suất khi sử dụng Danh sách <> của các đối tượng so với ArrayList của các đối tượng là tối thiểu - khoảng 10% tốc độ tăng (số của tôi là 1.982/1.81/1.233/1.089). Phải thừa nhận rằng, việc tăng hiệu suất cho List <> vs ArrayList là rất hữu hình đối với int, nó không chỉ ở đó cho các lớp. – JustLoren

+0

@JustLoren - Ngay cả khi không có lỗi "nhỏ" thì tính toán cũng giống nhau. Và tôi đã viết cả trong câu trả lời của tôi (ở trên) và trong bài đăng trên blog, sự khác biệt về hiệu suất chủ yếu là do loại boxing/unboxing có giá trị –

0

Sử dụng Generics cũng có nghĩa là mã của bạn sẽ đơn giản và dễ sử dụng hơn nếu bạn muốn tận dụng những thứ như LINQ trong các phiên bản C# sau.