Подтвердить что ты не робот

Первоначальная емкость типов сбора, например. Словарь, список

Некоторые типы коллекций в .Net имеют необязательный параметр конструктора "Начальная емкость". Например:

Dictionary<string, string> something = new Dictionary<string,string>(20);

List<string> anything = new List<string>(50);

Кажется, я не могу найти, какая начальная емкость по умолчанию для этих объектов в MSDN.

Если я знаю, что я буду хранить только 12 предметов в словаре, не имеет смысла установить начальную емкость примерно на 20?

Мое рассуждение заключается в том, что емкость растет так же, как и для StringBuilder, которая удваивается каждый раз, когда нажимается мощность, и каждое перераспределение является дорогостоящим, почему бы не предустановить размер того, что, как вы знаете, будет содержать ваши данные, с какой-то дополнительной комнатой на всякий случай? Если начальная емкость равна 100, и я знаю, что мне понадобится всего около дюжины или около того, кажется, что остальная часть этой памяти распределена ни за что.

4b9b3361

Ответ 1

Если значения по умолчанию не документированы, причина в том, что оптимальная начальная емкость - это деталь реализации и может быть изменена между версиями каркаса. То есть вы не должны писать код, который принимает определенное значение по умолчанию.

Конструктор перегрузки с пропускной способностью для случаев, когда вы лучше знаете, чем класс, какое количество элементов следует ожидать. Например, если вы создаете коллекцию из 50 значений и знаете, что это число никогда не будет увеличиваться, вы можете инициализировать коллекцию емкостью 50, поэтому ей не придется изменять размер, если емкость по умолчанию ниже.

Тем не менее, вы можете определить значения по умолчанию, используя Reflector. Например, в .NET 4.0 (и, возможно, в предыдущих версиях),

  • a Список <T> инициализируется с емкостью 0. Когда добавляется первый элемент, он повторно инициализируется емкостью 4. Впоследствии, всякий раз, когда достигается пропускная способность, емкость удваивается.

  • Словарь <T> также инициализируется с емкостью 0. Но он использует совершенно другой алгоритм для увеличения емкости: он увеличивает емкость всегда до простых чисел.

Ответ 2

Проверяя источник, емкость по умолчанию для List<T> и Dictionary<TKey, TValue> равна 0.

Ответ 3

Если вы знаете размер, сообщите об этом; небольшая оптимизация в большинстве "малых" случаев, но полезная для больших коллекций. В основном я бы об этом беспокоился, если бы я выбрал "приличный" объем данных, так как тогда он может не выделять, копировать и собирать несколько массивов.

Большинство коллекций действительно используют стратегию удвоения.

Ответ 4

Другая проблема с ConcurrentDictionary (в настоящее время) и использование его конструктора для установки начального размера заключается в том, что его производительность, похоже, затруднена.

Например, вот пример кода и эталонных тестов Я попробовал.

Я запустил код на своей машине и получил аналогичные результаты.

То есть, когда задан начальный размер, он не делает ничего, чтобы увеличить скорость ConcurrentDictionary при добавлении объектов. Технически я думаю, что это должно быть потому, что ему не нужно тратить время или ресурсы, чтобы изменить его размер.

Да, он может работать не так быстро, как обычный словарь, но я бы все же ожидал, что ConcurrentDictionary с его первоначальным размером будет иметь стабильную и быструю производительность, чем ConcurrentDictionary, у которой нет своего начального размера, особенно когда один заранее знает количество элементов, которые будут добавлены к нему.

Таким образом, мораль этой истории устанавливает начальный размер, не всегда гарантируя улучшение производительности.