2013-03-15 35 views
8

Câu hỏi rất đơn giảnCó thể sao chép tham chiếu đến đối tượng từ điển nhanh hơn hoặc truy cập trực tiếp từ điển từ điển không?

là mã này

public Dictionary<string, SomeObject> values = new Dictionary<string, SomeObject>(); 

void Function() 
{ 
    values["foo"].a = "bar a"; 
    values["foo"].b = "bar b"; 
    values["foo"].c = "bar c"; 
    values["foo"].d = "bar d"; 
} 

cùng nhanh như mã này

public Dictionary<string, SomeObject> values = new Dictionary<string, SomeObject>(); 

void Function() 
{ 
    var someObject = values["foo"]; 
    someObject.a = "bar a"; 
    someObject.b = "bar b"; 
    someObject.c = "bar c"; 
    someObject.d = "bar d"; 
} 

lẽ thường nói với tôi rằng nó phải được nhanh hơn để tìm kiếm các tài liệu tham khảo trong từ điển một lần và lưu trữ nó ở đâu đó để nó không cần phải tra cứu nhiều lần, nhưng tôi thực sự không biết từ điển hoạt động như thế nào.

Vì vậy, nó có nhanh hơn hay không? Và tại sao?

+3

Có * bạn * thực sự đã thử kiểm tra xem có sự khác biệt về tốc độ không? –

+2

tại sao bạn không chạy thử nghiệm điểm chuẩn và xem –

+0

Không, tôi không biết làm cách nào để chuẩn mã số – Petr

Trả lời

7

Đúng, bạn đúng. Cách tiếp cận đầu tiên của bạn thực hiện tra cứu từ điển 4 lần, trong khi phương pháp thứ hai thực hiện một lần. Thứ hai chắc chắn là tốt hơn. Tuy nhiên, trong cuộc sống thực, tra cứu từ điển rất nhanh, vì vậy trừ khi bạn có một từ điển lớn sự khác biệt sẽ không đáng chú ý, có thể thậm chí không thể đo lường được.

+1

Lưu ý rằng kích thước của từ điển không có liên quan ở đây, vì tra cứu là O (1). Tất cả những vấn đề đó là bạn tra cứu bao nhiêu lần, vì vậy nếu mã này nằm trong vòng lặp chạy nhiều lần (ngay cả khi từ điển được tra cứu không lớn), thì điều đó có thể quan trọng. – Servy

+0

Đáng chú ý, có thể là không. Có thể đo lường được, chắc chắn. Mã phải tính toán giá trị băm và thực hiện tra cứu. Ngoài ra, kích thước của từ điển không liên quan. Tìm kiếm thứ gì đó trong từ điển 1.000.000 mục sẽ mất không lâu hơn trong từ điển chỉ có 1.000 mục. Trừ khi từ điển đầy (hệ số tải cao). Sau đó, nó hoạt động giống như một tìm kiếm tuần tự. –

+0

Để giải trí, tôi đã tạo từ điển 1.000 và 1.000.000 mục nhiều lần, sau đó thực hiện 5.000.000 tra cứu trên chúng (phím Guid). Mất khoảng 2,5 giây để thực hiện tra cứu đối với 1.000 mục và 3,5 giây để thực hiện chúng với 1.000.000 mục. Kết quả rất nhất quán. Vì vậy, tôi muốn nói rằng kích thước của từ điển không quan trọng, mặc dù không đáng kể. –

1

Tôi đã tò mò. Thử nghiệm đơn vị sau đây (có thể) cho thấy phương pháp thứ hai nhanh hơn khoảng 25%. (121 mili giây so với 91 mili giây). Đi từ 6 lĩnh vực đến 2 thu hẹp khoảng cách, 40 ms so với 33 ms. Tôi nói có thể vì tôi đã viết điều này khá nhanh và tôi không tin rằng nó miễn dịch để đo một số tác dụng phụ, nhưng nó cho thấy hành vi mong đợi, vậy tại sao lại hỏi nó. (hah)

using System; 
using System.Text; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using System.Diagnostics; 

namespace TestProject1 
{ 

public class DataObject 
{ 
    public string A { get; set; } 
    public string B { get; set; } 
    public string C { get; set; } 
    public string D { get; set; } 
    public string E { get; set; } 
    public string F { get; set; } 
} 

[TestClass] 
public class UnitTest1 
{ 
    public static Dictionary<string, DataObject> dict = new Dictionary<string, DataObject>(); 
    static string lookie; 

    [ClassInitialize()] 
    public static void MyClassInitialize(TestContext testContext) { 

     Random rand = new Random(123545); 
     for (int i = 0; i < 10000; i++) 
     { 
      string key = rand.NextDouble().ToString(); 
      DataObject dob = new DataObject(); 
      dict.Add(key, dob); 
      if (i == 4567) 
       lookie = key; 
     } 

    } 


    [TestMethod] 
    public void TestMethod() 
    { 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     for (int j = 0; j < 100000; j++) 
     { 
      dict[lookie].A = "val" + j; 
      dict[lookie].B = "val" + j; 
      dict[lookie].C = "val" + j; 
      dict[lookie].D = "val" + j; 
      dict[lookie].E = "val" + j; 
      dict[lookie].F = "val" + j; 
     } 
     sw.Stop(); 

     System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds); 

     sw.Reset(); 
     sw.Start(); 
     for (int j = 0; j < 100000; j++) 
     { 
      DataObject dob = dict[lookie]; 
      dob.A = "val" + j; 
      dob.B = "val" + j; 
      dob.C = "val" + j; 
      dob.D = "val" + j; 
      dob.E = "val" +j; 
      dob.F = "val" +j; 
     } 
     sw.Stop(); 

     System.Diagnostics.Debug.WriteLine(sw.ElapsedMilliseconds); 
    } 
    } 
} 
+0

Bạn đã làm timings trên bản phát hành bản phát hành không có trình gỡ rối được đính kèm chưa? 25% có vẻ ... quá mức. –

6

Joe hoàn toàn đúng, nhưng như thế vẫn chưa đủ tôi đã thực hiện một bài kiểm tra rõ ràng đơn giản:

static void Main(string[] args) 
{ 
    var dict = new Dictionary<string, Foo>(); 
    var number = 10000000; 
    for (int i = 0; i < number; i++) 
    { 
     dict[i.ToString()] = new Foo(); 
    } 

    var watch = new Stopwatch(); 

    watch.Start(); 
    for (int i = 0; i < number; i++) 
    { 
     var key = i.ToString(); 
     dict[key].A = "a"; 
     dict[key].B = "b"; 
     dict[key].C = "c"; 
     dict[key].D = "d"; 
    } 

    watch.Stop(); 
    Console.Out.WriteLine(watch.ElapsedMilliseconds); 

    watch.Reset(); 

    watch.Start(); 
    for (int i = 0; i < number; i++) 
    { 
     var key = i.ToString(); 
     var foo = dict[key]; 

     foo.A = "a"; 
     foo.B = "b"; 
     foo.C = "c"; 
     foo.D = "d"; 
    } 

    watch.Stop(); 
    Console.Out.WriteLine(watch.ElapsedMilliseconds); 
} 

class Foo 
{ 
    public string A { get; set; } 
    public string B { get; set; } 
    public string C { get; set; } 
    public string D { get; set; } 
} 

Trên máy tính của tôi này kết quả đầu ra để:

3423 
2113 
Press any key to continue . . . 

Có chỉ 1 tra cứu chắc chắn làm giảm tổng thời gian cho số lượng lớn.

+0

Khi nghi ngờ, hãy đo! –

+1

Vì vậy, khoảng 1,3 giây 'sự khác biệt hơn 10 triệu lần lặp? Đó là khá nhiều định nghĩa của "xuống trong tiếng ồn", như xa như tối ưu hóa chương trình là có liên quan. –

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