.Net中的非常大的集合会导致内存不足异常

时间:2010-09-07 08:52:37

标签: c# .net f# gcallowverylargeobjects

我正在测试.Net中的集合有多大。从技术上讲,任何集合对象都可以增长到物理内存的大小。

然后我在服务器上测试了以下代码,该服务器有16GB内存,运行Windows 2003服务器和Visual Studio 2008.我测试了F#和C#代码,并在运行时查看了任务管理器。我可以看到,在增加2GB内存之后,该程序因内存不足异常而崩溃。我确实在属性页面中将目标平台设置为x64。

open System.Collections.Generic

let d = new Dictionary<int, int>()

for i=1 to 1000000000 do
    d.Add(i,i)

我对C5集合库进行了相同的测试。结果是C5中的字典可能耗尽整个内存。代码使用C5:

let d = C5.HashDictionary<int, int> ()
for i=1 to 1000000000 do
    d.Add(i,i)

任何人都知道为什么?

4 个答案:

答案 0 :(得分:42)

Microsoft CLR的最大对象大小限制为2GB,即使是64位版本也是如此。 (我不确定这个限制是否也存在于其他实现中,例如Mono。)

该限制适用于每个单个对象 - 而不是所有对象的总大小 - 这意味着使用某种复合集合可以相对容易地进行解决。

这里有一个讨论和一些示例代码......

似乎很少有官方文档提到这个限制。毕竟,它只是当前CLR的实现细节。我唯一知道的是on this page

  

运行64位托管时   应用程序在64位Windows上   操作系统,你可以创建一个   对象不超过2千兆字节   (GB)。

答案 1 :(得分:21)

在4.5之前的.NET版本中,最大对象大小为2GB。从4.5开始,如果启用gcAllowVeryLargeObjects,您可以分配更大的对象。请注意,string的限制不受影响,但“数组”也应该包含“列表”,因为列表由数组支持。

答案 2 :(得分:11)

要清楚,Dictionary使用单个数组来添加对。它每次充满时会增长(加倍?)。当有512万个对象时,它的大小为2GByte(具有32位对象指针,并假设完美分布)。添加一个元素会使Dictionary尝试再次将数组大小加倍。吊杆。

C5 HashDictionary使用线性散列,可能使用每个包含多个(16?)元素的存储区数组。它应该在以后遇到同样的问题。

答案 3 :(得分:1)

“允许大对象”只会有助于摆脱OOM异常。

当需要存储很多对象时,您将看到的问题是 GC停顿(暂停)。我们所做的是从数据库“隐藏”数据,后者变成了 一个非常实用的解决方案。

请参阅:https://www.infoq.com/articles/Big-Memory-Part-3

您可以使用充当字典的缓存: https://github.com/aumcode/nfx/tree/master/Source/NFX/ApplicationModel/Pile

请参阅缓存部分