.Netの特定のコレクション型には、オプションの「初期容量」コンストラクタパラメータがあります。例えば:
Dictionary<string, string> something = new Dictionary<string,string>(20);
List<string> anything = new List<string>(50);
MSDNで、これらのオブジェクトのデフォルトの初期容量を見つけることができないようです。
辞書に12個程度のアイテムしか保存しないことがわかっている場合、初期容量を20などに設定しても意味がありませんか?
私の推論は、容量がヒットするたびに倍になるStringBuilderの場合と同じように容量が増加し、各再割り当てにコストがかかると仮定すると、サイズを事前に設定して、データを保持できることがわかっているので、追加の部屋は念のため?最初の容量が100で、必要なのは1ダースかそれ以上だとわかっている場合、そのメモリの残りは何にも割り当てられていないようです。
デフォルト値が文書化されていない場合、その理由は、最適な初期容量が実装の詳細であり、フレームワークのバージョン間で変更される可能性があることです。つまり、特定のデフォルト値を想定するコードを記述しないでください。
コンストラクタ容量のあるオーバーロードは、あなたがよりよく知っている場合のためのものですクラスよりも期待されるアイテムの数。たとえば、50の値のコレクションを作成し、この数が決して増加しないことがわかっている場合、50の容量でコレクションを初期化できるため、デフォルトの容量が小さい場合にサイズを変更する必要はありません。
つまり、Reflectorを使用してデフォルト値を決定できます。たとえば、.NET 4.0(およびおそらく以前のバージョン)では、
a List <T>は容量0で初期化されます。最初の項目が追加されると、容量4に再初期化されます。その後、容量に達すると、容量は2倍になります。
dictionary <T>も容量0で初期化されます。しかし、それは容量を増やすために完全に異なるアルゴリズムを使用します:常に素数になる容量を増やします。
ソースのチェック、両方のデフォルト容量List<T>
およびDictionary<TKey, TValue>
は0です。
サイズがわかっている場合は、それを教えてください。ほとんどの「小さな」ケースではマイナーな最適化ですが、より大きなコレクションには役立ちます。私は主に「まともな」量のデータを投入する場合、これについて心配します。これにより、複数の配列を割り当て、コピー、収集する必要がなくなるためです。
ほとんどのコレクションは確かに倍増戦略を使用しています。
ConcurrentDictionary(現在)のもう1つの問題と、コンストラクターを使用して初期サイズを設定すると、パフォーマンスが低下するように見えます。
たとえば、 ここにいくつかのサンプルコードとベンチマークがあります 試してみました。
私は自分のマシンでコードを実行し、同様の結果を得ました。
つまり、初期サイズが指定されている場合、オブジェクトを追加するときにConcurrentDictionaryの速度を上げることはありません。技術的には、サイズ変更に時間やリソースを費やす必要がないため、すべきであると考えています。
はい、それは通常のディクショナリほど速く実行されない可能性がありますが、初期サイズが設定されているConcurrentDictionaryは、特に事前にわかっている場合は、初期サイズが設定されていないConcurrentDictionaryよりも一貫性があり、高速であることが期待されます追加されるアイテムの数。
したがって、ストーリーの教訓は、初期サイズを設定することが必ずしもパフォーマンスの向上を保証するわけではないということです。