gpt4 book ai didi

.net - C# Collection 的最大容量在哪里定义?

转载 作者:行者123 更新时间:2023-12-04 01:44:52 25 4
gpt4 key购买 nike

我尝试将大量元素添加到一个集合中,每个元素简单的数据传输对象具有五个基本数据类型的属性,没什么特别的。

在循环中添加新条目时,我总是收到 OutOfMemoryException。有趣的是,在尝试添加第 8388608 个元素(即 8*1024*1024)时,我总是遇到异常。因此,我假设在此类集合中允许的容量(元素数量)方面存在内置限制,但我找不到任何有关它的信息。

这个极限真的存在吗?我在哪里可以找到这个记录?

最佳答案

这是一个 OutOfMemoryException,所以这里的问题不是集合的大小或容量:它是应用程序中的内存使用。诀窍是您不必用完机器甚至进程中的内存来获得此异常。

我认为正在发生的是你正在填满大对象堆。随着集合的增长,他们需要在后台添加存储空间以容纳新项目。一旦分配了新存储并复制了项目,旧存储将被释放并且应该有资格进行垃圾回收。

问题是,一旦超过特定大小(以前是 85000 字节,但现在可能有所不同),垃圾收集器 (GC) 会使用称为大对象堆 (LOH) 的东西跟踪您的内存。当 GC 从 LOH 中释放内存时(这种情况很少发生),内存将返回到您的操作系统并可供其他进程使用,但该内存中的虚拟地址空间仍将在您自己的进程中使用.你的程序地址表中会有一个很大的空洞,因为这个空洞在大对象堆上,它永远不会被压缩或回收。

您在 2 的精确幂上看到此异常的原因是大多数 .Net 集合使用加倍算法为集合添加存储。它总是会在需要再次加倍的地方抛出,因为在那之前 RAM 已经被分配了。

那么,一个快速的解决方案是利用大多数 .Net 集合的一个很少使用的功能。如果您查看构造函数重载,大多数集合类型都有一个允许您在初始构造期间设置容量的类型。这个容量不是硬性限制——它只是一个起点——但它在一些情况下很有用,包括当你的集合会变得非常大时。您可以将初始容量设置为淫秽的……希望大小足以容纳您的所有物品,或者至少只需要“加倍”一次或两次。

您可以通过在控制台应用程序中运行以下代码来查看这种效果:

var x = new List<int>();
for (long y = 0; y < long.MaxValue; y++)
x.Add(0);

在我的系统上,这会在 134217728 项之后引发 OutOfMemory 异常。 134217728 * 每个 int 4 个字节只是(并且正好)512MB 的 RAM。它不应该抛出,因为这是进程中唯一具有任何实际大小的东西,但无论如何它都会抛出,因为旧版本的集合丢失了地址空间。

现在让我们更改代码以设置容量,如下所示:
var x = new List<int>(134217728 * 2);
for (long y = 0; y < long.MaxValue; y++)
x.Add(0);

现在,我的系统在抛出时一直到 268435456 个项目(1GB 的 RAM),这是因为它无法将 1GB 翻倍,这要归功于进程使用的其他 ram 占用了 2GB 虚拟地址表限制的一部分(即:循环计数器以及来自集合对象和进程本身的任何开销)。

我无法解释的是它不允许我使用 3 作为乘数,即使那只会是(!)1.5GB。一个使用不同乘数试图找出我能得到多大的小实验表明这个数字是不一致的。有一次我能够达到 2.6 以上,但后来不得不退回到 2.4 以下。我猜有什么新发现。

如果此解决方案确实为您获得了足够的空间,那么还有一个 trick you can use to get 3GB of virtual address space ,或者您可以强制您的应用程序针对 x64 而不是 x86 或 AnyCPU 进行编译。如果您使用的是基于 2.0 运行时的框架版本(从 .Net 3.5 开始的任何版本),您可以尝试更新到 .Net 4.0 或更高版本,据报道这在这方面要好一些。如果没有这些,您将不得不完全重写您如何处理数据,这可能涉及将数据保存在磁盘上,并且一次只在内存中保存一个项目或项目的小样本(缓存)。我真的推荐最后一个选项,因为其他任何事情最终都可能会意外地再次中断(如果您的数据集一开始就这么大,那么它也可能会增长)。

关于.net - C# Collection<T> 的最大容量在哪里定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13954546/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com