C#中Hashset<string>
的内存限制是什么?
我看到.NET的每个对象的内存限制为2Gb?这些信息仍然准确吗?它适用于Hashsets吗?
我目前正在开发一个适用于大型hashset的应用程序,我已经看到,只要我为64位环境构建dll,只有当我的8GB RAM笔记本电脑达到其内存限制时,才能获得OutOfMemory。
如果我有16Gb RAM,对象会增加,直到达到硬件限制?
答案 0 :(得分:2)
每个对象有2GB限制,但请记住,当它是类中的字段时,引用类型仅使用指针大小(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
是一个结构,那么根据它的大小,你的内存会很快耗尽。)