2011-05-05 30 views
10

我們有一個應用程序,其中包含大量的對象在幾個Dictionary s,其中一些在應用程序的生命週期中不斷增長(交易應用程序與大量的工具和不斷增長的訂單/交易)。大對象堆友好IDictionary

由於大對象堆的碎片化,我們在OutOfMemoryException上遇到了問題。

爲了解決這個問題,我試着編寫一個'大'字典,它是作爲一個兩級字典實現的,其中所有的葉子字典都不足以在LOH上分配。我使用了一致的哈希算法,以避免當單個桶變得太大時不得不重新哈希整個字典。來自C5集合庫的一致哈希'circle'是TreeDictionary

我的問題是,C#有沒有更好的數據結構(或者我所描述的更好的實現)?

更新

這是「大」的字典執行:我理解爲無論是LOH堆閾值是在規範它不是萬無一失https://gist.github.com/956621

,也不是每個字典條目的大小或縮放算法。然而,這是目前我能想到的最好的方法,以避免應用程序在中午時被炸燬。

+1

這可能有助於說明您在現有實施中看到了哪些問題? – 2011-05-05 04:29:27

+0

如果您將字典用作平面對象的鍵值存儲,則可以考慮使用內存映射文件。 – hsmiths 2011-05-05 04:49:53

+0

您是否證實了您沒有在任何地方「泄漏」內存(如持有的引用「內存泄漏」) – 2011-05-05 04:59:20

回答

1

我認爲這需要改變算法。

從我聽說和理解的角度來看,GC在打包和碎片整理方面非常出色。所以你的問題源於簡單的事實,你將太多的數據存入內存。

你在內存中保存了多少數據?

您是否想過使用數據庫?緊湊的一個可能就足夠了。

或者直接告訴你的客戶,要正確運行你的應用程序,他需要16 GB的內存。如果你的應用程序需要所有這些16 GB的內存,那肯定有什麼問題。

編輯:從不同的側面你的問題 尋找和閱讀你的編輯後,我得到了一個問題:有多大你的對象?或者它們是否包含長列表或數組?你多久去掉/添加這些對象?

我覺得問題可能不在字典本身,但對象,太大,被刪除/添加太頻繁。也許使用某種捕捉或游泳池可能是有利可圖的。如果您使用列表,然後通過預先定位創建這些列表。

也許使用不可變結構而不是可變類可以緩解碎片。

+0

+1「你在內存中保存了多少數據?」不要調整你的字典,用你最近獲得的經驗重新評估你的需求。 – 2011-05-05 05:05:52

+0

長期目標是減少我們在記憶中的交易次數,但短期內不可行。不幸的是,用64位操作系統取代所有交易者的32位XP機器都不是。 – SimonC 2011-05-05 06:10:33

+0

+1本地數據庫是唯一最好的選擇 – 2011-05-05 06:29:41

3

當字典是應用程序中最大的字典時,它是一個不幸的數據結構。當哈希表變得太滿時,它的大小通常會增加一倍,並且在調整大小的時候需要150%的過度分配,這正是關鍵時刻。散列表的工作量非常大,但它需要連續的分配來強調堆算法。

您可以用多級哈希表來消除這些缺點,例如使用哈希碼的一個字節作爲256個哈希表的索引。這肯定會增加一些開銷,但更重要的是,這個和其他策略充滿了危險,通過擺弄隨機性,比如你得到的hashcode,並且潛在地使事情變得更多,性能更差。使用這種方法需要良好的理論基礎和堅實的實證檢驗。但它可以工作。

另一個策略是爲最壞的情況預先分配最大的數據結構並儘早分配它。沒有必要進行細粒度的分配,但現在如果它應該耗盡,現在你面臨着災難性失敗的幽靈。這是一個選項。

+0

我認爲我擁有的多級哈希算法在性能方面可以。我們在可能的情況下預分配數組,但在最壞的情況下直接分配數組並不總是可行/可取的。 – SimonC 2011-05-05 06:18:16

+0

它可以通過在Dictionary構造函數中指定容量來預分配表嗎? – hsmiths 2011-05-05 18:51:21

+0

@shmith:如果你知道可能會有一百萬條記錄,那麼馬上說出來很有幫助。但是,當你達到一百萬人時,真正的痛苦開始了。 – 2011-05-05 20:00:12