.NET中的非常大的收集导致内存外例外
-
01-10-2019 - |
题
我正在测试一个收藏在.NET中的大小。从技术上讲,任何收集对象都可以生长到物理内存的大小。
然后,我在SEVER中测试了以下代码,该密码具有16GB内存,运行Windows 2003 Server和Visual Studio2008。我测试了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)
有人知道为什么吗?
解决方案
Microsoft CLR具有2GB的最大对象大小限制,即使是64位版本。 (我不确定此限制是否也存在于单声道等其他实现中。)
限制适用于每个 单身的 对象 - 不是所有对象的总尺寸 - 这意味着使用某种复合集合的合成集合可以相对容易解决。
这里有讨论和一些示例代码...
似乎几乎没有官方文件指的是该限制。毕竟,这只是当前CLR的实现细节。我知道的唯一提到的是 在本页面:
当您在64位Windows操作系统上运行64位托管应用程序时,您可以创建一个不超过2 GB(GB)的对象。
其他提示
在4.5之前的.NET版本中,最大对象大小为2GB。从4.5开始,您可以分配较大的对象 gcallowverylargeobjects 已启用。请注意,极限 string
不受影响,但“数组”也应覆盖“列表”,因为列表由数组支持。
要明确,词典使用单个数组添加对。每次填满时,它都会成长(加倍?)。当有5.12亿个对象时,其尺寸为2GByte(带有32位对象指针,并假设分配完美)。添加一个元素使词典尝试再次将数组大小加倍。繁荣。
C5 Hashdictionary使用线性哈希,并且可能使用一系列包含多个(16?)元素的桶。它应该遇到相同的问题(非常多)。
“允许大物体”只会有助于摆脱OOM例外。
当一个人需要存储很多对象时,您会看到的问题是GC摊位(暂停)。我们所做的是“隐藏” GC的数据,这变成了非常实用的解决方案。
看到这个: https://www.infoq.com/articles/big-memory-part-3
您可以使用用作字典的缓存:https://github.com/aumcode/nfx/tree/master/source/nfx/applicationmodel/pile
参见缓存部分