Храните большое количество объектов в памяти в течение длительного времени - PullRequest
2 голосов
/ 19 февраля 2009

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

Может ли это вызвать проблемы с ГХ? Я продолжаю слышать, что долгоживущие объекты влияют на производительность ГХ и заставляют его занимать больше времени во время сбора, есть ли способ избежать этого? Насколько я понимаю, словарь (и объекты) должны заканчиваться в Gen2, который GC не собирает, если в системе недостаточно памяти (пожалуйста, исправьте меня, если я ошибаюсь), так что, если в системе много памяти, будет ли GC по-прежнему собирать Gen2 с той же частотой? Должны быть и другие приложения, которые кешируют большие объемы данных тоже долгое время, интересно, как они избегают проблем с GC.

Любые предложения действительно ценятся ...

Ответы [ 4 ]

3 голосов
/ 19 февраля 2009

При записи около 1М словари, лежащие в основе массива, неизбежно окажутся в LOH. Учитывая это, возможно, было бы неплохо предварительно выделить его в размере, соразмерном количеству записей, которые он в конечном итоге содержит (это может плохо отозваться и может быть проблемой в тестовом режиме).

Объекты в словаре должны обеспечивать очень хорошую реализацию хэш-кода. Это не относится к использованию памяти напрямую, просто к эффективности поиска. Однако, если вы торгуете более высоким коэффициентом загрузки за меньшее использование памяти, плохой хэш может в конечном итоге ухудшить поведение словарей до такой степени, что он больше не будет O (1).

Долгосрочные предметы, которые он содержит, должны либо:

  1. (Наилучший случай) не содержат полей экземпляров, которые являются ссылочными типами.

    • Тогда GC не нужно проходить через каждый из этих объектов в массиве (реализация GC может не выполнять эту оптимизацию, поэтому ваш пробег может варьироваться).
  2. Убедитесь, что ваше приложение не переключается на Mid Life Crisis стиль поведения

    • Запуск большего количества коллекций gen2, которых вы хотите избежать.
  3. Любые содержащиеся в них ссылки не должны указывать на кучи Gen0 или Gen1

    • Это может привести к большому количеству барьеров записи, что замедлит ваши коллекции gen 0 / gen 1.

Поскольку вы заявляете, что это кеш, но не упоминаете вашу политику хранения, я думаю, что этот совет тоже заслуживает упоминания.

Некоторое указание типа объектов, которые вы кэшируете, может иметь значение 4 / 8МБ или непрерывная память - это ужасно много даже при использовании современных кешей процессоров, поэтому частые запросы к кешу могут иметь более низкую производительность, чем более плотный, меньший кеш с лучшая политика хранения.

1 голос
/ 19 февраля 2009

Вы понимаете, что сценарий верен, если система не жаждет памяти. Коллекции Gen2 должны быть редкими, и, следовательно, хранение многих долгоживущих объектов не должно быть проблемой.

Если бы вам пришлось тщательно кодировать, чтобы избежать «проблем» с GC, GC не справился бы со своей работой очень хорошо.

Единственная область, которая действительно нуждается в беспокойстве, - это большие выделения (одно выделение> 86 КБ) с большим количеством таких поступающих и продолжающихся, может быть проблемой.

0 голосов
/ 19 февраля 2009

Вы должны быть осторожны, чтобы предметы не попали в кучу больших объектов (> 85 КБ). Если они остаются резидентными, это не проблема, но если данные обмениваются и извлекаются, вы можете получить фрагментацию памяти, поскольку LOH не сжимается.

0 голосов
/ 19 февраля 2009

Я не могу решить, мудро ли это, но если вы не хотите, чтобы его собирали, используйте следующий код:

GC.KeepAlive(object);
...