2012-05-14 48 views
13

Tôi đang tạo thư viện mà tôi đang thử nghiệm hiệu suất. Trong đó tôi tạo ra một Dictionary<Type, X> một lần. Các mục hiện được chèn theo thứ tự ngẫu nhiên. Từ điển vẫn không thay đổi trong suốt thời gian của ứng dụng.Thay thế nhanh hơn từ điển <Type, X>?

Sau đó, nó thường được sử dụng để tra cứu các mục. Tra cứu là một trong những nút cổ chai lớn hơn trong thư viện.

Có, tôi đang tối ưu hóa vi mô, nhưng để tìm hiểu. Tôi tự hỏi nếu có một cách tốt hơn để có được hiệu suất tra cứu?

Cập nhật

Tôi đã sử dụng dotTrace để đo hiệu suất. Báo cáo + dotTrace nằm trong máy tính ở nhà của tôi, vì vậy tôi không có báo cáo ở đây (có thể đã tải lên ở một nơi khác).

tôi đã sử dụng các bài kiểm tra tìm thấy ở đây: https://github.com/danielpalme/IocPerformance

Định nghĩa từ điển được tìm thấy ở đây: https://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container/ContainerBase.cs

(tôi đã tạo container thứ sáu cuối cùng, tôi không mong đợi quá nhiều)

Update2

Performance breakdown

Dictionary.TryGetValue mất 101ms tổng số Resolve (tổng số 251ms) là 40,2% nếu tôi đã giải thích các con số chính xác.

+4

a: Có bao nhiêu loại/cặp trong dữ liệu, b: điều gì khiến bạn nghĩ rằng đó là một nút cổ chai? (tức là bạn đã đo đạc như thế nào? chúng ta có thể thấy bất kỳ mã tra cứu nào không?) –

+2

và c: là những người gọi sử dụng các loại tĩnh (tức là 'int', vv) hay chúng đang sử dụng các đối tượng' Loại' do sự phản ánh? nếu người gọi biết các loại tĩnh, có một số thủ thuật có thể được sử dụng –

+0

@MarcGravell: bạn có thể mở rộng một chút về các thủ thuật đó (câu trả lời hoặc liên kết) vì nó là một chủ đề thú vị không. cảm ơn – mathieu

Trả lời

1

Điểm chuẩn hiệu suất cho container IoC từ Daniel Palme (nhưng những người khác cũng) là một chút sai lầm, vì điểm chuẩn giải quyết đồ thị đối tượng rất cạn từ container (mặc dù nó không rõ ràng cho thấy việc thực hiện sự khác biệt giữa các container là lớn). Điều này là không thực tế, bởi vì hầu hết các ứng dụng (sử dụng DI đúng cách) sẽ có đồ thị đối tượng chứa các liều của các đối tượng. Khi thực hiện điều này, chỉ đối tượng gốc cần được giải quyết và khi vùng chứa được viết đúng cách, điều này có nghĩa là bạn sẽ chỉ có một cuộc gọi đến Dictionary<T,V>.TryGetValue mỗi yêu cầu (web) trong hầu hết các trường hợp (hoặc nhiều nhất là một vài). Bởi vì điều này, hiệu suất của Dictionary<T, V> không thực sự là một vấn đề.

Tôi tin rằng phần lớn nhất của chi phí hiệu suất của Dictionary<T,V> trong đó TKeySystem.Type, phải làm với chi phí hiệu suất của việc tạo mã băm cho Type nhất định. Mỗi khi bạn gọi TryGetValue, Type.GetHashCode() phải được gọi. GetHashCode là ảo (không thể được nội tuyến) và phương thức đó gọi 3 phương thức ảo khác. Cuối cùng, một cuộc gọi tĩnh (bên ngoài) được thực hiện đến RuntimeHelpers.GetHashCode(key).

Nói cách khác, bạn có thể tối ưu hóa hiệu suất để viết một lớp từ điển cụ thể (không chung) sử dụng Type làm khóa và thay vì gọi Type.GetHashCode() bạn nên gọi RuntimeHelpers.GetHashCode(key).

UPDATE (2013/04/05):

Một vài tháng trở lại tôi đã cố gắng để cải thiện hiệu suất của container DI tôi duy trì và tôi chơi với tối ưu hóa phần từ điển. Tôi đã viết từ điển của riêng tôi gọi trực tiếp RuntimeHelpers.GetHashCode(key) (và bỏ qua các cuộc gọi ảo) nhưng cuối cùng hiệu suất đạt được quá nhỏ (khoảng 1% trong tiêu chuẩn của Palme) mà tôi quyết định hoàn nguyên các thay đổi mã này. Vì vậy, sự hiểu biết hiện tại của tôi là chi phí thực tế thực sự với Dictionary<Type, X> thực sự là tất cả mọi thứ xảy ra bên trong RuntimeHelpers.GetHashCode(key).

2

Nếu loại là thời gian biên dịch được xác định, bạn có thể cố gắng thực hiện nó như thế này:

static class ValueFor<T> 
{ 
    // you get another field per type T 
    public static X X { get; private set; } 

    internal static SetUpValue(X value) { X = value; } 
} 

Chỉ cần truy cập sử dụng này.

var myIntX = ValueFor<int>.X; 
+0

Thật không may là không. Ánh xạ được tạo bởi người dùng/dev tại thời gian chạy (như đối với tất cả các vùng chứa IoC) – jgauffin

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