2016-10-31 76 views
2

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

我见过.NET每个对象的内存限制为2Gb?这些信息是否准确?它适用于Hashsets吗?

我目前正在研究一个与大型哈希集一起工作的应用程序,并且我已经看到,只要我为64位环境构建dll时,只有当我的8GB RAM笔记本电脑达到其内存限制时,才会获得OutOfMemory。

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

+0

重复? HTTP://计算器。com/a/1088044/993547 –

+1

2GB限制适用于单个对象,并会影响阵列的最大大小。但是,如果存储在哈希集中的'T'是类,那么只有32位或64位引用存储在哈希集中,实际对象实例及其大小在HashSet的。一般而言,OutOfMemory意味着.NET真的耗尽了内存,它绝不应该意味着某些任意对象认为这个值已经达到了最高。 –

+0

2GB限制不再那么简单;有'gcAllowVeryLargeObjects'选项 - 但即使启用了'int.MaxValue'限制仍然适用;在'T' ='string'的情况下,虽然 - **如果**'HashSet '受大数组限制,您可能会变大一些!不是微不足道的 –

回答

2

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

阵列存储器大小被计算如下(忽略固定开销):

对于结构类型的数组:阵列中

  • 阵列存储器大小= #elements *各元素
的大小

对于引用类型的数组:

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

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

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

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

我怀疑你存储在HashSet中的对象是引用类型,所以它只对内部HashSet数组中的每个对象使用64位,而每个对象的全部大小远大于64位 - 它提供了超过2GB的总大小。

综观referencesource为HashSet的示出了下面的阵列用于:

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结构在x64占用16个字节当T是参考类型时,表示当使用的插槽数超过2GB/16 = 128M个元素时,HashSet将抛出OutOfMemory

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

+0

@LaRage由于您正在存储字符串,因此您可以在获取OutOfMemory之前存储〜128 * 1024 * 1024的字符串。如果启用大对象,我*认为*由于元素过多,您可以在得到异常之前存储〜2 * 1024 * 1024 * 1024。但是你需要测试一下才是确定的!我并不确定。 –