我正在测试.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)
任何人都知道为什么?
答案 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
请参阅缓存部分