C# 哈希集的内存限制是什么?

C# 哈希集的内存限制是什么?,c#,.net,performance,hashset,bigdata,C#,.net,Performance,Hashset,Bigdata,C#中的Hashset有哪些内存限制 我见过.NET对每个对象的内存限制是2Gb?这个信息还准确吗?它适用于哈希集吗 我目前正在开发一个使用大型哈希集的应用程序,我已经看到,一旦我为64位环境构建了dll,只有当我的8GB RAM笔记本电脑达到其内存限制时,我才会失去内存 如果我有16Gb的RAM,那么对象会一直增加直到达到硬件限制吗?每个对象有2GB的限制,但是请记住,引用类型仅在类中的字段中使用指针大小(x64为8字节) 阵列内存大小的计算如下(忽略固定开销): 对于结构类型的数组: 数组

C#中的
Hashset
有哪些内存限制

我见过.NET对每个对象的内存限制是2Gb?这个信息还准确吗?它适用于哈希集吗

我目前正在开发一个使用大型哈希集的应用程序,我已经看到,一旦我为64位环境构建了dll,只有当我的8GB RAM笔记本电脑达到其内存限制时,我才会失去内存


如果我有16Gb的RAM,那么对象会一直增加直到达到硬件限制吗?

每个对象有2GB的限制,但是请记住,引用类型仅在类中的字段中使用指针大小(x64为8字节)

阵列内存大小的计算如下(忽略固定开销):

对于结构类型的数组:

  • 数组内存大小=#数组中的元素*每个元素的大小
对于引用类型的数组:

  • 数组内存大小=#数组中的元素*参考大小(x8x为4字节,x64为8字节)
所以一个哈希集可以引用超过2GB限制的对象。只是,如果将类中每个字段的大小相加(引用类型为64位,结构类型为完整大小),则必须小于2GB

例如,您可以有一个包含16x1GB字节数组的类

还请注意,可以将应用程序配置为允许阵列大小大于2GB,尽管一维阵列中的最大元素数仍然不能超过2G(2*1024*1024*1024)

我怀疑您存储在HashSet中的对象是引用类型,因此内部HashSet数组中的每个对象只使用64位,而您的每个对象的完整大小远远大于64位,这使得总大小超过2GB

查看HashSet的referencesource显示使用了以下数组:

private int[] m_buckets;
private Slot[] m_slots;
其中
Slot
的定义如下:

internal struct Slot {
    internal int hashCode;      // Lower 31 bits of hash code, -1 if unused
    internal T value;
    internal int next;          // Index of next entry, -1 if last
}
T
是引用类型时,每个
Slot
结构在x64上占用24个字节,这意味着当使用的Slot数量超过2GB/24=85M个元素时,哈希集将抛出OfMemory


(如果
T
是一个结构,那么取决于它的大小,内存会很快用完。)

复制?2GB限制适用于单个对象,例如,它将影响阵列的最大大小。但是,如果存储在哈希集中的
T
是类,则哈希集中只存储32位或64位引用,实际对象实例及其大小在哈希集中的上下文中并不重要。OutOfMemory通常意味着.NET确实耗尽了内存,这绝不意味着某个任意对象决定这是它能达到的最高值。@LasseV.Karlsen它可以合法地抛出,因为某些支持内部结构无法调整大小;我不知道如何实现
HastSet
,但很难想象这样一种场景:在存储字符串的地址空间用完之前,HashSet就用完了。您必须存储小字符串,很难保持它们的唯一性。如果平均字符串长度为10个字符,那么仅字符串就需要10 GB。GC btw非常粗糙。64位程序中的可用地址空间受到最大页面文件大小及其增长速度的限制。磁盘始终是需要过多内存的程序的解决方法。无论是分页文件、平面文件还是数据库,实际上都没有任何区别。@LaRage因为您存储的是字符串,所以在退出内存之前,您可以存储其中的~128*1024*1024。如果启用大对象,我认为在由于元素太多而导致异常之前,可以存储~2*1024*1024*1024。但是你需要测试一下才能确定!我真的不确定。请原谅我的无知,但是在x64上,插槽结构不应该占用24字节吗?与类不同,结构不是为了紧凑性而打包/重新排序的。@mafu你说得对-它应该是24字节。我会更新答案的。顺便说一句,这个数字低得离谱,这是微软的100%错,因为它又一次“640K对任何人来说都应该足够了”