Есть ли способ уменьшить емкость словаря, если известно, что он имеет фиксированный размер?

После прочтения отличного принятого ответа на этот вопрос:

Как реализован словарь c # /. net 3.5 ?

Я решил установить свою начальную емкость на большое предположение, а затем обрезать ее после того, как прочитал все значения. Как я могу это сделать? То есть, как я могу обрезать словарь, чтобы сборщик мусора позже собирал неиспользуемое пространство?

Моя цель - оптимизация. У меня часто есть большие наборы данных, и временные потери для небольших наборов данных приемлемы. Я хочу избежать накладных расходов на перераспределение и копирование данных, которые возникают при небольших начальных объемах в больших наборах данных.


person philologon    schedule 15.03.2014    source источник
comment
Изменение размера словаря действительно дорогое удовольствие. Обязательно сравните оба подхода, потому что сокращение также может стоить много времени.   -  person usr    schedule 16.03.2014
comment
Учитывая, что увеличение емкости происходит в геометрической прогрессии, это не является особенно дорогостоящим при агрегировании по всем добавляемым элементам. Выполнение всей этой работы может оказаться не таким большим улучшением, как вы ожидали.   -  person Servy    schedule 16.03.2014
comment
Наблюдая, как приходят ответы на этот вопрос, я также пытаюсь сделать что-то подобное со списком, но в этом случае я знаю начальный размер списка: 3,039,104. Установив этот начальный размер, я получаю улучшение скорости примерно на 4% - в значительной степени не стоит того, на что указали Серви и другие.   -  person philologon    schedule 16.03.2014


Ответы (3)


В .NET 5 есть метод TrimExcess делает именно то, что вы просите:

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

person Phate01    schedule 05.06.2021

Согласно Reflector, класс Dictionary никогда не сжимается. void Resize() жестко запрограммирован так, чтобы всегда удваивать размер.

Вероятно, вы можете создать новый словарь и использовать соответствующий конструктор для копирования элементов. Это будет совершенно неэффективно.

Или добавьте свой собственный словарь к существующему в качестве чертежа. Это меньше работы, чем вы думаете сначала.

Обязательно сравните оба подхода.

person usr    schedule 15.03.2014
comment
Я должен добавить, 7 лет спустя, что этот ответ отражает состояние предыдущих версий .NET. - person usr; 29.06.2021

Вы можете сначала поместить свои данные в список. Затем вы знаете размер списка и можете создать словарь с этой емкостью (теперь точно подходящий для данных, которые вам нужны) и заполнить его.

Разрешение динамического изменения размера списка (по мере добавления элементов) должно быть дешевле, чем разрешение изменять размер словаря. (Но, как отмечали другие, проверьте производительность самостоятельно!) Изменение размера словаря включает операцию повторного хеширования, что означает, что GetHashCode каждого элемента будет вызван снова, а также ссылка будет скопирована в новую структуру данных. Изменение размера списка означает просто копирование ссылок, поэтому это должно быть дешевле.

person Joe White    schedule 15.03.2014