HashSet 的内存限制是多少?

dor*_*ido 5 .net c# performance hashset bigdata

Hashset<string>C# 中a 的内存限制是什么?

我看到 .NET 每个对象的内存限制为 2Gb?这些信息仍然准确吗?它适用于哈希集吗?

我目前正在开发一个与大型哈希集一起使用的应用程序,并且我发现,一旦我为 64 位环境构建了 dll,只有当我的 8GB RAM 笔记本电脑达到其内存限制时,我才会出现内存不足的情况。

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

Mat*_*son 6

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

数组内存大小计算如下(忽略固定开销):

对于结构类型的数组:

  • 数组内存大小=数组中的#元素*每个元素的大小

对于引用类型的数组:

  • 数组内存大小 = 数组中的#元素 * 参考大小(x8x 为 4 字节,x64 为 8 字节)

因此,HashSet 可以引用总计远远超过 2GB 限制的对象。只是,如果将类中每个字段占用的大小(引用类型的 64 位,以及结构类型的完整大小)相加,它必须小于 2GB。

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

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

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

查看 HashSet 的参考源发现使用了以下数组:

private int[] m_buckets;
private Slot[] m_slots;
Run Code Online (Sandbox Code Playgroud)

其中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
}
Run Code Online (Sandbox Code Playgroud)

看起来每个Slot结构体在 x64 上T是引用类型时占用 24 个字节,这意味着当使用的槽数量超过 2GB/24 = 85M 元素时,HashSet 将抛出 OutOfMemory 异常

(如果T是一个结构体,那么根据它的大小,你会很快耗尽内存。)

  • 顺便说一下,这个值低得离谱,100% 都是微软的错,因为它又出现了“640K 应该对任何人来说都足够了”的时刻 (2认同)