2011-12-27 26 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数组非常平均。