HashSet的内存限制是什么?

时间:2016-10-31 11:10:59

标签: c# .net performance hashset bigdata

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

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

我目前正在开发一个适用于大型hashset的应用程序,我已经看到,只要我为64位环境构建dll,只有当我的8GB RAM笔记本电脑达到其内存限制时,才能获得OutOfMemory。

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

1 个答案:

答案 0 :(得分:2)

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

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

对于结构类型的数组:

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

对于引用类型的数组:

  • 数组内存大小=数组中的#elements *引用大小(x8x为4字节,x64为8字节)

因此,HashSet可以引用总计超过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
}

Slot是引用类型时,看起来每个T结构在x64上占用16个字节,这意味着当使用的插槽数超过2GB / 16 = 128M时,HashSet将抛出OutOfMemory

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