2011-12-27 59 views
10

嘗試在HashSet<Int32>中添加23997908th項目時拋出System.OutOfMemoryException類型的例外。OutOfMemoryException將更多項目添加到非常大的HashSet時<Int32>

我們需要維護一個整數大小爲Int32.MaxValue的高性能唯一集合,即2147483647HashSetInt32只能在其中存儲23997907項。尋找解決此問題的建議。

+3

出於純粹的好奇心:你需要什麼? – 2011-12-27 06:45:11

+1

http://blog.mischel.com/2008/04/09/hashset-limitations/ – 2011-12-27 06:57:28

+0

@MikeNakis:正如後文所述,我們需要保持一個高性能獨特的整數集合來滿足我們的一些要求 – Debasis 2011-12-27 07:00:56

回答

14

HashSet(Of T)對象的容量是對象可容納的元素的數量。對象的容量會隨着元素的添加而自動增加。

,如果你使用的是64位系統,您可以通過在運行時環境中gcAllowVeryLargeObjects的enabled屬性設置爲true的Hashset增加的最大容量高達2個十億 元素。

您可以從配置文件中啓用此設置,

<configuration> 
<runtime> 
    <gcAllowVeryLargeObjects enabled="true" /> 
    </runtime> 
</configuration> 

入住此MSDN鏈接設置配置。

更新:

以上配置gcAllowVeryLargeObjects支持在Net框架4.5只。

+2

Framework 4.5以上只有... – 2011-12-27 07:08:48

+1

我突然對.NET 4.5感到興奮。我已經碰到了2GB的限制太多次了。 – 2011-12-27 07:11:00

+0

@MitchWheat:是的,我忘了提。更新我的答案。謝謝 – mehul9595 2011-12-27 07:19:57

9

HashSet增加一倍。因此,當您在列表中有23,997,907個項目並嘗試添加下一個項目時,它會嘗試將其後備數組的大小加倍。並且該分配導致它超出可用內存。我假設你在32位系統上運行這個功能,因爲在64位系統上,HashSet<object>可以容納8900萬個物品。 32位運行時限制約爲6170萬項。

你需要做的是預先分配HashSet來保存儘可能多的項目,你需要。遺憾的是,沒有直接的方式來做到這一點。 HashSet沒有一個構造函數,它將預先分配給定的容量。

但是,您可以創建一個List,用它初始化HashSet,然後在HashSet上調用Clear。這最終會給你一個HashSet,它沒有任何項目,但是你所請求的最大容量。我在博客文章中展示瞭如何做到這一點:More on .NET Collection Sizes

HashSet大小的限制是由於.NET中的兩個千兆字節限制所致。沒有一個對象可以大於兩個千兆字節。由於分配開銷,該數字實際上略小。

+0

Dot net只允許在Int32列表中添加134,217,728個項目 – Debasis 2011-12-27 08:12:08

+0

@Debasis:如果您在64位模式下運行,我期望列表'給你超過5億條目。您的1.34億個項目可以達到超過512 MB的內存,這很容易超過您在32位運行時分配的內存。即使在64位模式下,您可以創建的最大「HashSet」也接近1.34億。 – 2011-12-27 10:10:16

0

在這一點上,我認爲你需要使用數據庫來保存你的項目(或他們的哈希鍵),因爲這是太多的項目存儲在默認的.NET對象。您也可以編寫一個與HashSet具有相同屬性的自定義對象,但這可能會更麻煩,只是使用數據庫表來存儲散列。

1

爲了解決這個問題,我創建了一個實現HashSet方法和屬性(Contains,Add,Count,...)的類,並在後臺保留一個HashSets數組來存儲實際數據。第一個實現在每個HashSet中一個接一個地完成,並在滿時移到數組中的下一個。最新採用散列鍵作爲內部HashSet數組的索引。這對我來說效果很好,因爲這些鍵非常隨意,所以將值分配給HashSets數組非常平均。