2011-08-30 24 views
15

an established guideline để nhận mã băm không nên cấp phát bộ nhớ vì điều này sẽ tác động tiêu cực đến việc tìm kiếm bảng băm bằng cách gọi trình thu thập rác.Hiệu suất từ ​​điển C#: Mặc định chuỗi so sánh GetHashCode() phân bổ bộ nhớ vi phạm nguyên tắc, do đó phá hoại hiệu suất?

Tuy nhiên, thất bại này chính xác là những gì tôi nhìn thấy những gì tôi cấu hình ứng dụng của tôi trong đó sử dụng một System.Collections.Generic.Dictionary

Way sâu thẳm trong một vòng lặp rất chặt chẽ tôi thấy như sau trong kết quả hồ sơ của tôi:

  • [3,47%] TryGetValue (TKey, TValue &) (... từ điển)
    • [3,47%] FindEntry (TKey) (... từ điển)
      • [3,47%] GetHashCode (string) (System.CultureAwareComparer)
        • [3,46%] GetHashCodeOfString (String, CompareOptions) (System.Globalization.CompareInfo)
          • [3,39%] [Garbage Collection ]
          • [0.01%] [Người Gởi Suspendended]

Đó là toàn bộ kế toán cây con từ hồ sơ.

Tôi không phải là chuyên gia dày dặn trong loại công việc cụ thể này, vì vậy tôi có thể đọc những lá trà này không chính xác. Nhưng có vẻ với tôi như GetHashCodeOfString "phải" cấp phát bộ nhớ và mời bộ thu gom rác ngắt chương trình của tôi ở giữa vòng lặp này, tôi muốn TẤT CẢ VÀ TÁI, và điều này chiếm phần lớn đáng kinh ngạc của chi phí của vòng lặp này.

Là một sang một bên, here is an additional piece of evidence suggesting this code allocates memory

bước tiếp theo của tôi sẽ là để khởi tạo từ điển với Comparer thứ và tái chạy thử nghiệm của tôi.

Nhưng tôi muốn biết nếu có sự khôn ngoan hiện có ở đó xung quanh vấn đề này. Dường như các từ điển có khóa chuỗi là phổ biến và chi phí của một thứ phổ biến như vậy có thể được khám phá tốt. Tôi tìm thấy các phân tích sau đây, nhưng nó tập trung vào việc so sánh thực tế là nguyên nhân gây ra sự khốn khổ, và không phải là phương pháp mã băm phân bổ bộ nhớ.

Có ai có thể đề xuất cách thích hợp để sử dụng từ điển có các phím chuỗi tránh được sự cố này không?

câu hỏi cụ thể tôi có bao gồm:

  • Nếu tôi sử dụng comparitor thứ sẽ phân bổ biến mất?
  • Nếu không, tôi có cần phải viết người so sánh của riêng mình và điều đó sẽ làm cho việc phân bổ biến mất không?
  • Nếu tôi làm cho người so sánh biến mất, tôi có thể thực sự mong đợi một cải tiến thực sự, theo liên kết giới thiệu MSFT mà tôi đã bắt đầu không?

EDIT: Crud, xấu, nhưng điều này không có thuộc tính so sánh mặc định, chúng tôi đã đặt thành ignoreCase. Không chắc chắn nếu điều này tác động đến kết quả, nhưng vì ignoreCase sẽ tác động đến sự bình đẳng, nó phải có một số tác động lên băm.

UPDATE: Ran một thử nghiệm bằng cách sử dụng comparer thứ tự (vẫn với IgnoreCase), và viết lại những kết quả ban đầu ra đến 100% chi phí = TryGetValue nên nó sẽ được nhiều táo để táo

gốc:

  • 100% TryGetValue
    • 100% FindEntry
      • 99,5% CultureAwareComparer.GetHashCod e
        • 99,5% CompareInfo.GetHashCodeOfString
          • 95,86% [Garbage Collection]
          • 3,31% [Chủ đề Bị treo]
      • 0,5% CultureAwareComparer.Equals
        • 0.5% So sánh
          • 0,5% [thu gom rác thải]

TT:

  • 100% TryGetValue
    • 1 00% FindEntry
      • 47,22% CultureAwareComparer.Equals
        • 47,22% [Garbage Collection]

Ngoài ra còn xuất hiện để được giảm đáng kể trong tổng thể thời gian dành cho TryGetValue. Tôi đã không cẩn thận để đảm bảo rằng tất cả mọi thứ đều bằng nhau, nhưng điều này chiếm 46 giây trong một bài kiểm tra căng thẳng 10 phút trong lần chạy đầu tiên, và trong chạy orindal nó chiếm 252 mili giây. Hãy xem xét giai thoại đó, không phải là chi phí tương đối dự kiến.

Có vẻ như toàn bộ chi phí của hàm băm, được sử dụng là 99 +% chi phí, hiện nay "miễn phí" đến mức thậm chí không xuất hiện trong hồ sơ, mà tôi cho là đang chạy ở chế độ lấy mẫu.

Tôi đoán giây này từ trên đường mà bạn nên sử dụng so sánh thứ tự.

Tôi vẫn không thể PROVE bản thân mình tại sao chi phí GC đóng góp quá nhiều vào kết quả hồ sơ đầu tiên, nhưng từ các nhận xét bên dưới tôi cho rằng tôi phải tin rằng nó KHÔNG phân bổ bộ nhớ heap được quản lý, nhưng , nó có xu hướng là chức năng được "ngẫu nhiên" GCed bởi các hoạt động khác trên các chủ đề khác, vì quá trình này thực sự là sử dụng chế độ máy chủ gc.

Có thể điều này cho thấy rằng vòng lặp chặt chẽ này có xu hướng đồng thời với mã phân bổ hạnh phúc ở một nơi khác.

+0

Khóa của bạn dài bao lâu? – svick

+0

Hầu như tất cả các phím sẽ nằm trong phạm vi 15-30 ký tự. – rice

+0

Crack đầu tiên tại kết quả profiler chỉ đến trong .... cho đến nay nó trông giống như chuyển sang so sánh thứ tự loại bỏ hiệu suất thu gom rác thải hit. Không phải là kết quả vững chắc. – rice

Trả lời

9

Theo mặc định, khi bạn sử dụng các phím string, string.GetHashCode() được sử dụng. Phương thức này không phân bổ bộ nhớ nào trên heap, và sẽ khá nhanh.

Nhưng vì bạn đang sử dụng trường hợp bỏ qua, CultureAwareComparer.GetHashCode() được sử dụng thay thế. Phương thức đó gọi (như có thể được nhìn thấy từ kết quả hồ sơ của bạn) CompareInfo.GetHashCodeOfString(), do đó gọi hàm không được quản lý là InternalGetGlobalizedHashCode(). Cả hai phương thức được quản lý đều không tạo ra bất kỳ phân bổ heap nào (như bạn có thể thấy nếu bạn nhìn chúng trong một trình dịch ngược). Tôi không thể nói những gì InternalGetGlobalizedHashCode() hiện, nhưng vì nó không được quản lý, tôi nghi ngờ nó làm cho bất kỳ phân bổ trên heap được quản lý. Trong mọi trường hợp, nó phải phức tạp hơn rất nhiều so với tính toán mã băm mặc định, đặc biệt vì nó là nhận thức về văn hóa và phải ghi nhớ các vấn đề như Turkish İ.

Điều này có nghĩa là bạn có thể có một số mã khác phân bổ bộ nhớ trên heap, điều này gây ra việc thu gom rác.

Và nếu bạn đang thực hiện hiệu suất tối đa, bạn nên tránh "trường hợp bỏ qua" và đặc biệt là các biến thể nhận biết văn hóa của nó.

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