2009-04-03 31 views
41

Khi sử dụng Guid làm chỉ mục cho Dictionary, tốt hơn là sử dụng đối tượng Guid hoặc biểu diễn chuỗi của hướng dẫn?Hiệu suất - sử dụng đối tượng Guid hoặc chuỗi Guid là Key

Tôi vừa tái cấu trúc một số mã đang sử dụng chuỗi để sử dụng đối tượng, bởi vì có new Guid() cuộc gọi khắp nơi. Nhưng điều đó khiến tôi băn khoăn không biết vấn đề hiệu suất có thể là gì. (Các bộ sưu tập khá nhỏ, nhưng chúng được lặp lại nhiều lần.)

Trả lời

68

Guid nên nhanh hơn, vì so sánh đơn giản hơn - chỉ một vài byte trực tiếp. Chuỗi liên quan đến một dereference và rất nhiều công việc.

Tất nhiên - bạn có thể cấu ;-p

Bằng chứng:

Searching for 7f9b349f-f36f-94de-ad96-04279ddf6ecf 
As guid: 466; -1018643328 
As string: 512; -1018643328 
Searching for 870ba465-08f2-c872-cfc9-b3cc1ffa09de 
As guid: 470; 1047183104 
As string: 589; 1047183104 
Searching for d2376f8a-b8c9-4633-ee8e-9679bb30f918 
As guid: 423; 1841649088 
As string: 493; 1841649088 
Searching for 599889e8-d5fd-3618-4c4f-cb620e6f81bb 
As guid: 488; -589561792 
As string: 493; -589561792 
Searching for fb64821e-c541-45f4-0fd6-1c772189dadf 
As guid: 450; 1389733504 
As string: 511; 1389733504 
Searching for 798b9fe5-ba15-2753-357a-7637161ee48a 
As guid: 415; 779298176 
As string: 504; 779298176 
Searching for 12ba292e-8e59-e5d0-7d04-e811a237dc21 
As guid: 457; 558250944 
As string: 564; 558250944 
Searching for 05b3ce14-dfbf-4d3a-1503-ced515decb81 
As guid: 413; 1658205056 
As string: 504; 1658205056 
Searching for 8db4a556-0a65-d8cb-4d0d-0104245d18b8 
As guid: 415; 696231936 
As string: 506; 696231936 
Searching for c49cf80c-5537-fba5-eebd-8ad21bba09c4 
As guid: 459; 2100976384 
As string: 557; 2100976384 

dựa trên:

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
static class Program 
{ 

    static void Main() 
    { 
     Random rand = new Random(123456); 
     int COUNT = 1000; 
     Dictionary<Guid, int> guids = new Dictionary<Guid, int>(COUNT); 
     Dictionary<string, int> strings = new Dictionary<string, int>(
      COUNT, StringComparer.Ordinal); 

     byte[] buffer = new byte[16]; 
     for (int i = 0; i < COUNT; i++) 
     { 
      rand.NextBytes(buffer); 
      Guid guid = new Guid(buffer); 
      int val = rand.Next(); 
      guids.Add(guid, val); 
      strings.Add(guid.ToString(), val); 
     } 

     for(int i = 0 ; i < 10 ; i++) { 
      int index = rand.Next(COUNT); 
      Guid guid = guids.Keys.Skip(index).First(); 
      Console.WriteLine("Searching for " + guid); 
      int chk = 0; 
      const int LOOP = 5000000; 
      Stopwatch watch = Stopwatch.StartNew(); 
      for (int j = 0; j < LOOP; j++) 
      { 
       chk += guids[guid]; 
      } 
      watch.Stop(); 
      Console.WriteLine("As guid: " + watch.ElapsedMilliseconds 
        + "; " + chk); 
      string key = guid.ToString(); 
      chk = 0; 
      watch = Stopwatch.StartNew(); 
      for (int j = 0; j < LOOP; j++) 
      { 
       chk += strings[key]; 
      } 
      watch.Stop(); 
      Console.WriteLine("As string: " + watch.ElapsedMilliseconds 
        + "; " + chk); 
     } 
     Console.ReadLine(); 

    } 
} 
+5

Ồ, bạn sẽ không làm điều đó cho tôi?;) – Benjol

+1

Wow, bạn đã làm! Câu trả lời là của bạn, thưa bạn! – Benjol

+0

Dịch vụ với một nụ cười ;-p –

2

Các bộ sưu tập là khá nhỏ, nhưng họ nhận được rất nhiều lặp của lần

Nếu bạn đang lặp lại, không có khóa nào để so sánh chính. Nếu bạn đang thêm/sửa đổi hoặc tra cứu bằng khóa, thì các phím sẽ được băm và các băm được so sánh; chỉ khi các băm bằng nhau thì các phím sẽ được so sánh. Do đó, trừ khi bạn đang thực hiện rất nhiều hoạt động dựa trên khóa trên các từ điển lớn với nhiều va chạm băm, tốc độ của khóa tới các so sánh chính sẽ không phải là yếu tố chính.

+0

Vâng, từ ngữ xấu về phía tôi. Không có nhiều điểm có một từ điển nếu không có tra cứu! – Benjol

+0

Một từ điển đảm bảo các khóa là duy nhất và chèn O (log n); điều này có thể rất hữu ích ngay cả khi bạn chỉ lặp lại. – Richard

+0

(xem trả lời bình luận của bạn trên bài viết của tôi) –

1

Suy nghĩ đầu tiên của tôi là, đối tượng Guid nhanh hơn, nhưng nếu bạn nhận được một số đầu vào dưới dạng chuỗi và phải tìm kiếm nó trong một bộ sưu tập nhỏ (hashset) của GUID (không thay đổi thường xuyên), nó có thể được nhanh hơn để lưu trữ chúng như dây đàn, bởi vì:

  • Đối với tìm kiếm một chuỗi trong một GUID-điển, bạn phải phân tích chuỗi (bao gồm cả kiểm tra lỗi vv), tạo cấu trúc Guid, lấy mã băm , thực hiện tra cứu băm và so sánh cuối cùng của các byte GUID.

  • Để tìm chuỗi trong Từ điển chuỗi, bạn phải tạo mã băm của chuỗi (có thể nhanh hơn xây dựng cấu trúc Guid), tra cứu hàm băm và thực hiện so sánh chuỗi. Nếu, ví dụ, bạn mong đợi nhiều GUID không được trong các bộ sưu tập, so sánh băm sẽ không thường xuyên một bạn thậm chí không phải làm so sánh chuỗi (mất nhiều thời gian hơn so với GUID so sánh từ điểm 1 ở trên)

Nếu bạn đã có cấu trúc hướng dẫn làm đầu vào (dĩ nhiên vì bạn đã kiểm tra tính hợp lệ trên chuỗi đầu vào) thì tốt hơn nên sử dụng lại chúng làm chỉ mục trong từ điển.

NHƯNG: Từ quan điểm rõ ràng thiết kế (đó là quan trọng hơn nhiều so với thực hiện trong 99% của tất cả các mã), bạn nên sử dụng Guid cấu trúc và chỉ thay đổi điều đó, nếu bạn thực sự chạy vào khó khăn thực hiện (và hồ sơ cho thấy bạn có được lợi thế từ giải pháp chuỗi).

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