3

List<T>(initSize)C# .NET 4.0 がメモリを割り当てる方法を理解しようとしています。

私の問題は、List<foo>where クラスfooが少なくとも 20 バイトのメモリを必要とすることです。XのいずれかまたはX+60要素を持つことになる 2 つのケースがありますfoo。2つのケースのどちらになるかは、割り当て時にわかりません。

Xは 36,000 要素を超えているため、不必要なメモリ割り当てを最小限に抑えようとしています。回避できるのであれば、1 回に 2 回割り当てたくありませんList。私の理解では、割り当てのサイズ (36k 要素 * 4B 参照 ~= 144kB) が割り当てを大きなヒープにプッシュします。私の悩みに加えて、Dictionary<key, List<foo>>約 4,000 の要素を持つ があります。

私の質問:

  1. C# ランタイムは、最初に指定された容量を超える量を割り当てますか? たとえば、36,000 エントリに初期化した場合、36,000 より大きい次の 2 の累乗であるため、実際に 65,536 エントリが割り当てられているでしょうか?

  2. 2 番目の割り当てを回避するX+60のではなく、すべての場合に割り当てる必要がありますか? Xこの場合、60 はたまたま一定値であり、変化しません。


私の質問は似ていますが、次のものとは異なります。

.NET でのコレクションのメモリ割り当てList<T>-この質問で は初期化されないためです。

ディクショナリ、リストなどのコレクション タイプの初期容量は、 初期容量を指定する際の実装上の問題です。

List<T> を特定のサイズ (容量ではなく) に初期化する方法は? Array- vsと格闘しているようList<T>ですが、これは私の問題ではありません。

4

2 に答える 2

4

実装は次のようになります。

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 インターフェイスで定義されていないため、これが将来的に当てはまるかどうかは不明です。

于 2013-09-09T15:11:20.233 に答える
4

コンパイラは何も割り当てません。割り当ては実行時に行われます。仕組みList<T>は、必要に応じて内部のサイズを 2 倍にすることT[]です。初期サイズを指定すると、それが割り当てられ、必要に応じてそこから 2 倍になります。

Tあなたの例ではクラスであるため、リストには参照のみが保持されることに注意してください。つまり、85000 バイト以上の参照 (およびリスト自体のオーバーヘッド) がある場合にのみ、リストは LOH に割り当てられます。

また、リストにfooは余分なスペースのインスタンスが保持されないため、参照用です。

于 2013-09-09T15:10:20.393 に答える