【问题标题】:List<T> memory allocation with initial capacity具有初始容量的 List<T> 内存分配
【发布时间】:2013-09-13 02:58:14
【问题描述】:

我试图了解 C# .NET 4.0 List&lt;T&gt;(initSize) 如何分配内存。

我的问题是我有一个List&lt;foo&gt;,其中foo 类需要至少20 字节的内存。我有两种情况,我最终会得到foo 的X 或X+60 元素。我不知道在分配时会是这两种情况中的哪一种。

由于X 大于36,000 个元素,因此我试图尽量减少不必要的内存分配,如果可以避免的话,我不想为一个List 分配两次。我的理解是分配的大小(36k 个元素 * 4B 参考 ~= 144kB)将分配推到大堆上。更让我烦恼的是,我的 Dictionary&lt;key, List&lt;foo&gt;&gt; 包含大约 4,000 个元素。

我的问题:

  1. C# 运行时是否分配了超出初始指定容量的数量?例如,如果我初始化为 36,000 个条目,我是否真的分配了 65,536 个条目,因为这是 2 的下一个大于 36,000 的幂?

  2. 我是否应该在所有情况下都分配给X+60 而不是X 以避免第二次分配?在这种情况下,60 恰好是一个不会变化的常数值。


我的问题类似,但与以下不同:

Memory allocation for collections in .NET - 因为他们没有在这个问题中初始化List&lt;T&gt;。

Initial capacity of collection types, e.g. Dictionary, List - 是指定初始容量的实现问题。

How to initialize a List<T> to a given size (as opposed to capacity)? - 似乎在与Array 和List&lt;T&gt; 较量,这不是我的问题。

【问题讨论】:

  • 记录在案,LOH 分配的限制为 85000 字节。
  • doubles 除外,其阈值仅为 1000 个元素(8K 字节)
  • 好吧,Dictionary 类中有一个不必要的字段没有被使用,因此它增加了一点内存分配
  • @MatthewWatson 更具体地用于双精度数组。
  • 每个foo 有多大?如果如@BrianRasmussen 所指出的那样,每个字节都小于 85000 字节,那么它们将不会存储在 LOH 上。我不确定运行时将如何处理 List 本身。它可能最终会出现在 LOH 上。

标签: c# memory-management collections


【解决方案1】:

编译器不分配任何东西。分配发生在运行时。 List&lt;T&gt; 的工作方式是根据需要将其内部T[] 的大小加倍。如果您指定初始大小,它将根据需要分配并从那里加倍。

请记住,由于 T 在您的示例中是类,因此该列表仅包含引用。 IE。只有当您有超过 85000 字节的引用(加上列表本身的开销)时,才会在 LOH 上分配列表。

此外,由于列表不包含foo 的实例,因此多余的空间仅用于引用。

【讨论】:

    【解决方案2】:

    实现是这样的:

    public List(int capacity)
    {
        if (capacity < 0x0)
        {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
        }
        if (capacity == 0x0)
        {
            this._items = List<T>._emptyArray;
        }
        else
        {
            this._items = new T[capacity];
        }
    }
    

    所以它将使用确切的容量。这是否会在未来成为现实是不确定的,因为它不是由 List 接口定义的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      相关资源
      最近更新 更多