2012-05-14 39 views
13

我正在創建一個庫,我正在進行性能測試。在它中,我生成了一次Dictionary<Type, X>。這些項目目前以隨機順序插入。字典在應用程序生命週期內保持不變。比字典<Type, X>更快的替代嗎?

它經常用於查找項目。查找是圖書館中較大的瓶頸之一。

是的,我是微型優化,但要學習。我想知道是否有更好的方法來獲得查詢性能?

更新

我用dotTrace來衡量性能。報告+ dotTrace在我的家用計算機中,所以我沒有這裏的報告(可能已經上傳到別的地方)。

我曾經在這裏找到測試:

https://github.com/jgauffin/Griffin.Container/blob/master/Source/Griffin.Container/ContainerBase.cs

(我創建容器上週五,不要期望太多): https://github.com/danielpalme/IocPerformance

字典的定義在這裏找到Update2

Performance breakdown

Dictionary.TryGetValue總共需要101ms Resolve(總251毫秒),如果我正確解釋了數字,這是40.2%。使用這種

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; } 
} 

剛剛訪問:

+4

a:數據中有多少個類型/對,b:是什麼讓你認爲它是瓶頸? (即你是如何測量的?我們可以看到任何查找代碼嗎?) –

+2

和c:是使用靜態類型的調用者(即'int'等),還是因反射而使用'Type'對象?如果呼叫者靜態地知道類型,有一些技巧可以使用 –

+0

@MarcGravell:你可以在這些技巧(答案或鏈接)上稍微延伸一點,因爲它是一個有趣的主題。特別感謝 – mathieu

回答

1

的IoC容器業績比較基準從 丹尼爾·帕爾梅(但那些別人爲好)是有點誤導,因爲基準從容器解析很淺的對象圖(儘管它清楚地表明,性能容器之間的差異很大)。這是不切實際的,因爲大多數應用程序(正確使用DI)將具有包含多個對象的對象圖。當這樣做時,只需要解析根對象,並且當容器寫入正確時,這意味着在大多數情況下(或者最多隻有幾個),每個(web)請求只會有一次調用Dictionary<T,V>.TryGetValue。因此,Dictionary<T, V>的性能並不是真正的問題。

我相信Dictionary<T,V>性能成本,其中TKeySystem.Type,那最大的部分與產生的哈希碼定Type的性能成本做。每當您撥打TryGetValue時,都必須撥打Type.GetHashCode()。 GetHashCode是虛擬的(不能內聯),該方法調用3個其他虛擬方法。最後,一個靜態(外部)呼叫到RuntimeHelpers.GetHashCode(key)

換句話說,你將能夠優化性能寫一個特定的(非通用)字典類使用Type作爲密鑰,並且不是調用Type.GetHashCode()你應該叫RuntimeHelpers.GetHashCode(key)

更新(2013年4月5日):

幾個月前,我試圖改善DI容器我保持的性能和我打了優化詞典的部分。我寫了我自己的字典,直接調用RuntimeHelpers.GetHashCode(key)(並跳過了虛擬調用),但最終性能得到了很大的提高(約爲Palme的基準測試的1%),我決定恢復這些代碼更改。所以我目前的理解是Dictionary<Type, X>的實際性能成本實際上是發生在RuntimeHelpers.GetHashCode(key)內的所有事情。

2

如果類型是編譯時定義的,您可以嘗試實現它是這樣。

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

不幸的是沒有。映射是在運行時由用戶/ dev創建的(對於所有IoC容器) – jgauffin