Большой Gen 0 кучи в .NET, тратить память? - PullRequest
7 голосов
/ 07 января 2012

У меня есть веб-приложение ASP.NET / C #, которое использует много памяти.

ANTS Memory Profiler и PerfMon показывают, что моя куча Gen 0 быстро увеличивается до размера около 1 ГБ во время Application_Start. Я прочитал здесь , что счетчик PerfMon для кучи Gen 0 фактически показывает «бюджет» для поколения 0, а не размер (который я понимаю, что не вся эта память является частью частного рабочего набора процесс?). Однако профилировщик ANTS показывает около 700 МБ «неиспользуемой памяти, выделенной для .NET», и это делает , по-видимому, частью частного рабочего набора процесса (как сообщается в taskmgr). Я предполагаю, что этот большой объем неиспользуемой памяти связан с большой кучей Gen 0.

То, что происходит в Application_Start, когда это происходит, заключается в том, что я в цикле while, читающем около миллиона строк из SqlDataReader. Они используются для заполнения большого кэша для последующего использования. Учитывая это, очевидным виновником большого количества неиспользуемой памяти была фрагментация кучи больших объектов, но я не думаю, что это так, поскольку я предварительно выделяю больше, чем необходимо для моего большого объекта кэша. Чтобы быть уверенным, я даже попытался закомментировать часть цикла, которая фактически добавляет к моему объекту кэша; это не имело никакого значения в количестве неиспользованной памяти, выделенной.

В качестве теста я пытался часто форсировать сборку мусора поколения 0 во время цикла (вопреки всем рекомендациям, я знаю), и это приводило к тому, что размер кучи gen0 оставался около 128 МБ, а также приводил только к нескольким МБ неиспользуемой свободной памяти. Но это также увеличило нагрузку на мой процессор и заставило Application_Start занять слишком много времени.

Мои вопросы:

1) Что может вызвать увеличение размера кучи Gen 0?

2) Это проблема? В частности, может ли это быть причиной выделения большого количества неиспользуемого пространства .NET?

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

1 Ответ

4 голосов
/ 07 января 2012

Gen 0 содержит «самые молодые, недавно выделенные объекты» и отделен от LOH. Это звучит так, как будто вы выделяете тонны и тонны небольших объектов (все ошибки, связанные с этими записями кэша, по звуку этого), которые не укоренены (что демонстрируется частыми GC, уменьшающими размер), но не очищаются своевременно, потому что GC еще не посчитал это необходимым. GC просто еще не видел необходимости в очистке. Сколько оперативной памяти у машины? Я предполагаю, что вы не пользуетесь пейджингом.

Насколько я понимаю, .NET может возвращать куски неиспользованной кучи в ОС, когда GC считает, что она больше не нужна (например, из-за того, что пространство кучи не использовалось в течение длительного времени). Вы наблюдали за приложением в течение длительного периода времени, чтобы увидеть, происходит ли это? Если вы не пользуетесь пейджингом, я не думаю, что это проблема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...