在 CLR 4.0 中,单个对象的大小仍限制为 2 GB?

Posted

技术标签:

【中文标题】在 CLR 4.0 中,单个对象的大小仍限制为 2 GB?【英文标题】:Single objects still limited to 2 GB in size in CLR 4.0? 【发布时间】:2010-11-08 10:45:16 【问题描述】:

据我了解,.NET 中的单个实例有 2 GB 的限制。因为到目前为止我主要在 32 位操作系统上工作,所以我没有对此给予太多关注。在 32 上,但这或多或少是人为的限制。但是,得知this limitation also applies on 64 bit .NET 时,我感到非常惊讶。

由于诸如List<T> 之类的集合使用数组来存储项目,这意味着运行在 32 位上的 .NET 应用程序将能够在列表中保存两倍于在 64 位上运行的相同应用程序的引用类型项目少量。这在我看来是相当令人惊讶的。

有谁知道 CLR 4.0 中是否解决了这个限制(我目前没有 4.0 安装)。

【问题讨论】:

2012 年更新:从 .NET 4.5 开始,在 x64 系统上,开发人员现在可以分配大于(远大于)2GB 的对象。 2GB的限制已经死了。 centerspace.net/blog/nmath/large-matrices-and-vectors/… 正确的链接似乎是centerspace.net/blog/nmath/large-matrices-and-vectors 即使更正的链接也失效了:( 尝试此链接以获取有关绕过 2GB 限制的信息 (MSDN) msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx 更正链接:centerspace.net/large-matrices-and-vectors 【参考方案1】:

比这更糟糕 - 你是进程空间,当你在 32 位的 .NET 中工作时,它比理论限制要小得多。在 32 位 .NET 应用程序中,我的经验是,您总是会在 1.2-1.4gb 内存使用量左右开始出现内存不足错误(有些人说他们可以达到 1.6...但我从未见过)。当然,这在 64 位系统上不是问题。

话虽如此,一个 2GB 的引用类型数组,即使在 64 位系统上,也是大量的对象。即使使用 8 字节引用,您也可以分配一个包含 268,435,456 个对象引用的数组——每个引用都可以非常大(最多 2GB,如果它们使用嵌套对象则更多)。这比大多数应用程序真正需要的内存要多。

CLR team blogged about this 的成员之一,有一些解决这些限制的方法的选项。在 64 位系统上,执行 BigArray 之类的操作将是一个可行的解决方案,可以将任意数量的对象分配到一个数组中——远远超过 2gb 的单个对象限制。 P/Invoke 也可以让你分配更大的数组。


编辑:我也应该提到这一点 - 我认为 .NET 4 的这种行为根本没有改变。自 .NET 开始以来,这种行为一直没有改变。


编辑:.NET 4.5 现在可以在 x64 中通过在 app.config 中设置 gcAllowVeryLargeObjects 来明确允许对象大于 2gb。

【讨论】:

我知道 32 位的所有限制,但这并不是我的问题的重点。令人惊讶的是,64 位的情况实际上更糟。我会看一下博客文章。感谢您的链接。 没问题 - 我只是补充说,因为它在 64 位中确实不比 32 位差。理论上的限制是对象的 1/2,但由于您确实被限制为总共 1.4gb 的进程空间,因此无法使对象引用数组接近允许大小的一半。 (每个引用都需要它指向某些东西,以及引用的大小......所以在 .NET 32 位中,大多数时候你确实限制了大约 1/4gb 的引用)。 Brian:这只是 64 位与 32 位的另一个(尽管是次要的,IMO)缺点。不迁移到 64 位的原因有很多 - 但人们似乎忘记了这一点,认为 64 位自动更好。 我读到 Mono 在 C# 中支持 64 位数组(例如超过 2^32 个条目的数组) 是的,Mono 就是这样做的。请注意,所有 CLR 实现都具有理论能力(所有数组都有 long LongLength 属性),但到目前为止只有 Mono 实际使用它。【参考方案2】:

.NET Framework 4.5 允许在 64 位平台上创建大于 2GB 的数组。此功能默认不启用,必须通过配置文件使用 gcAllowVeryLargeObjects 元素启用。

http://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx

【讨论】:

我没有注意到。感谢您的链接。 还是只有4GB!?为什么他们不能做真正的 64 位? @MarcGravell "数组中元素的最大数量是 UInt32.MaxValue。" @Rick k;那么带有uint.MaxValue 元素的int[] 有多大? 因此,如果您需要 byte[]...,则限制为 4GB【参考方案3】:

这在数值领域是一件大事。在 .NET 中使用数值类库的任何人都将其矩阵存储为下面的数组。这样就可以调用本机库来进行数字运算。 2GB 限制严重阻碍了 64 位 .NET 中可能的矩阵大小。更多here。

【讨论】:

我们已经与微软讨论过这个问题。它不太可能在 .NET 4.0 中得到修复,但他们似乎很乐意找到解决方案。我认为我们最终会得到长索引数组,但更有可能是某种巨型 blob 对象。 65536*65536 float 数组的性能与 65536 65536 float 数组的性能相比如何? 256 个浮点数的 256 个数组的性能将低于 256*256 数组的性能,因为后者将具有更好的缓存局部性,而前者则不会,但是如果访问的矩阵行足够局部化以受益从缓存位置来看,我认为处理器能够缓存对象表引用。

以上是关于在 CLR 4.0 中,单个对象的大小仍限制为 2 GB?的主要内容,如果未能解决你的问题,请参考以下文章

Atitit. C#.net clr 2.0  4.0新特性

CLR 强制执行的 1 MB 堆栈大小限制是针对线程还是整个应用程序/进程?

.Net 4.0 Windows 应用程序在 Windows Server 2008 下的 clr.dll 中崩溃

.net 4.0 中的特性总结:dynamic

配置邮箱和邮件大小限制 !

SQL Compact 4.0 和 Entity Framework 4.0:图像/Blob 限制?