将更多项添加到非常大的HashSet 时出现OutOfMemoryException
尝试在HashSet
添加23997908th
项时抛出类型System.OutOfMemoryException
类型的exception。
我们需要维护一个高性能的整数sizeof Int32
.MaxValue集合,即2147483647
。 Int32
HashSet
只能存储23997907
项目。 寻找解决此问题的建议。
HashSet(Of T)对象的容量是对象可以容纳的元素数。 随着元素的添加,对象的容量会自动增加。
如果您使用的是64位系统,则可以通过在运行时环境中将gcAllowVeryLargeObjects的enabled属性设置为true来将Hashset的最大容量增加到20亿个元素。
您可以从配置文件启用此设置,
检查此MSDN链接以设置配置。
更新:
上面的配置gcAllowVeryLargeObjects仅支持.Net framework 4.5。
HashSet
增长倍增。 因此,当列表中有23,997,907个项目并尝试添加下一个项目时,它会尝试将其后备arrays的大小加倍。 而这种分配导致它超过可用内存。 我假设你在32位系统上运行它,因为在64位系统上, HashSet
可以容纳超过8900万个项目。 在32位运行时中,限制大约为6170万个项目。
您需要做的是预先分配HashSet
以根据需要保存HashSet
项目。 不幸的是,没有直接的方法可以做到这一点。 HashSet
没有一个构造函数,它将使用给定的容量预先分配它。
但是,您可以创建一个List
,使用它来初始化HashSet
,然后在HashSet
上调用Clear
。 最终会给你一个没有项目的HashSet
,但是你要求的最大容量。 我在博客文章中展示了如何做到这一点: 有关.NET Collection Sizes的更多信息 。
HashSet
大小的限制是由于.NET中的两千兆字节限制。 没有单个对象可以大于2千兆字节。 由于分配开销,该数字实际上略小。
为了解决这个问题,我创建了一个实现HashSet方法和属性(Contains,Add,Count,…)的类,并在后台保存一组HashSets来存储实际数据。 第一个实现只是逐个最大化每个HashSet,并在满时移动到数组中的下一个。 最新版本将一个mod的哈希键作为内部HashSet数组的索引。 这对我很有用,因为键几乎是随机的,因此值到HashSets数组的分布非常均匀。
此时,我认为您需要使用数据库来保存您的项目(或其哈希键),因为这是太多要存储在默认.NET对象中的项目。 您还可以编写一个与HashSet具有相同属性的自定义对象,但仅使用数据库表来存储哈希值可能会更麻烦。
- IList 和IReadOnlyList
- 通过查找将循环展平为单个linq表达式
- 如何在自定义validation中调用默认的ServerCertificateValidationCallback?
- C#::何时使用事件或从事件处理接口派生的对象集合?
- 有没有办法导致传递给Control.BeginInvoke的委托的类型推断?
- 包含System.IO.Compression 时,当前上下文中不存在名称“ZipFile”
- LogicalOperationStack与.Net 4.5中的异步不兼容
- 如何获取System.Threading.Tasks.Task已完成的通知
- DateTime.ParseExact,包含7位数字/一个月或两位数月份