【问题标题】:What's the max items in a List<T>?List<T> 中的最大项目数是多少?
【发布时间】:2011-01-01 19:50:15
【问题描述】:

有人知道 List 中的最大项目数是多少吗?

如何增加该大小?或者是否有一个包含无限项的集合? (尽可能多的记忆,也就是说)

编辑:

当整数列表中的 Count = 134217728 时出现内存不足异常。获得了 3Gb 的 RAM,其中 2.2 正在使用中。声音正常

【问题讨论】:

  • @Tony - 你提到(cmets)你的内存一定很快就会用完......你看到了什么实际问题?
  • @Marc,编辑我的帖子有问题
  • 更新回答你的更新
  • 现在很好奇,为什么需要这么大的列表?
  • RAM 完全无关紧要。你机器中的芯片数量几乎与虚拟地址空间的大小无关;那就是你快用完了。 blogs.msdn.com/ericlippert/archive/2009/06/08/…

标签: c# collections


【解决方案1】:

List&lt;T&gt; 将被限制为数组的最大值,即 2GB(即使在 x64 中也是如此)。如果这还不够,则说明您使用了错误类型的数据存储。不过,您可以通过以正确的大小启动它来节省大量开销 - 通过将 int 传递给构造函数。

重新编辑 - 使用 134217728 x Int32,即 512MB。请记住,List&lt;T&gt; 使用了加倍算法;如果您通过Add 滴灌项目(没有先分配所有空间),它将尝试加倍至 1GB(在您已经持有的 512MB 之上,您的应用程序的其余部分 em>,当然还有 CLR 运行时和库)。我假设您使用的是 x86,所以您已经有 2GB 的限制每个进程,并且很可能您已经将“大对象堆”碎片化为死亡在添加项目时。

就个人而言,是的,此时开始内存不足听起来是正确的。


编辑:在 .NET 4.5 中,如果启用了 &lt;gcAllowVeryLargeObjects&gt; 开关,则允许使用大于 2GB 的数组。那么限制是 2^31 项。这对于引用数组(x64 中每个 8 字节)或大型 structs 数组可能很有用。

【讨论】:

  • 不,我的意思是 2GB 内存,由 CLR 强加。对于引用类型,这意味着(在 x64 上)每个引用 8 个字节,所以再分几次;-p
  • 上述的一个有趣的副作用是,理论上你可以在 x86 的数组中拥有更多的引用。实际上,在 x86 上,您永远不会设法分配一个大 有空间放置任何有用(和不同)对象的数组......在任何一种情况下,一个列表/这种大小的数组是完全错误的。
  • 我从未见过单个 .NET 进程分配超过 1.5Gb(至少在单个 AppDomain 中)。大多数 .NET 进程似乎在达到用于存储引用的数组大小限制之前就已经耗尽了本地地址空间中的内存。
  • 更多详情请看这个问题stackoverflow.com/questions/1087982/…
  • 顺便说一句,Mono CLR 是否允许您分配大于 2Gb 的数组。我认为他们支持这一点,因此实际上实现了 Array.LongLength 属性。
【解决方案2】:

列表限制为 21 亿个对象或内存大小,以先命中为准。

【讨论】:

  • 不,这是不正确的。任何对象都不能大于 2 GB,因此保存实际引用或值的数组将大大限制这一点。
  • 不完全是,它因存储的对象类型而异...例如,int 的列表限制对于 64 位进程只有 268435456。
【解决方案3】:

仅受内存限制。

编辑:不管有没有,2Gb 是极限!这个挺有意思的,BigArray, getting around the 2GB array size limit

【讨论】:

  • 那我的内存肯定快用完了?!?
  • 不仅受限于内存,还有一个硬性限制,因为底层数组支持。
【解决方案4】:

在 x64 机器上,使用 .Net Framework 4(不是客户端配置文件),在 Release 模式下为 Any CPU 编译,我可以消耗所有可用内存。我的进程现在是 5.3GB,我已经消耗了我 PC 上的所有可用内存 (8GB)。它实际上是一个 Server 2008 R2 x64。
我使用了一个基于 CollectionBase 的自定义 Collection 类来存储以下类的 61,910,847 个实例:

public class AbbreviatedForDrawRecord {
    public int DrawId { get; set; }
    public long Member_Id { get; set; }
    public string FactorySerial { get; set; }

    public AbbreviatedForDrawRecord() {

    }

    public AbbreviatedForDrawRecord(int drawId, long memberId, string factorySerial) {
        this.DrawId = drawId;
        this.Member_Id = memberId;
        this.FactorySerial = factorySerial;
    }
}

【讨论】:

    【解决方案5】:

    列表会自行动态增长以容纳尽可能多的项目 - 直到超出可用内存!

    来自 MSDN 文档:

    如果 Count 已经等于 Capacity,则通过自动重新分配内部数组来增加 List 的容量,并且在添加新元素之前将现有元素复制到新数组中。

    如果 Count 小于 Capacity,则此方法是 O(1) 操作。如果需要增加容量以容纳新元素,则此方法变为 O(n) 操作,其中 n 为 Count。

    【讨论】:

    • 当整数列表中的 Count = 134217728 时出现内存不足异常。获得了 3Gb 的 RAM,其中 2.2 正在使用中。听起来正常吗?
    • 看起来您只为该列表使用了半 GB(那么多整数 * 4 字节/int32)。您可能正在推动那里的边界。你需要计数这么高吗?您可以在没有 Count 的情况下初始化列表。
    • 计数就这么高,但我可以用另一种方式解决这个问题。不过,感谢您的所有回答。它帮助了我!
    • 乐于助人。您还可以通过使用字节列表或 int16 而不仅仅是“int”来减少内存占用。不过还是会有点多,当然这取决于适合您需要的类型。
    【解决方案6】:

    该接口将 Count 和 IndexOf 等定义为 int 类型,因此我假设 int.MaxValue 或 2,147,483,647 是您可以粘贴在列表中的最多项目。

    真的要问为什么你需要这么多,可能有一种更明智的方法来管理数据。

    【讨论】:

    • 我认为 C# 和 Java 使用 32 位整数作为索引是糟糕的设计,因为我们已经使用 64 位架构多年,很容易拥有超过 2GB 或 4GB 或 RAM。好的,这个大小的列表是值得商榷的,但是数组 作为缓冲区,文件,流大于 2GB 就可以了。然而,您需要脱离标准库来处理一个非常基本的问题。
    猜你喜欢
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多