OutOfMemoryException, размер файла дампа и размер кучи сборщика мусора

32-битное приложение .net, работающее на 32-битной машине, столкнулось с OutOfMemoryException. Затем я сделал полный дамп памяти, и хотя с помощью WinDbg я могу убедиться, что используется много памяти, мне интересно, почему мы получаем OOME, хотя размер кучи GC, согласно выводу WinDbg для «!eeheap -gc», равен всего около 1 ГБ, так что, похоже, осталось довольно много места до 1,5 ГБ .net.

Вот части вывода:

0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x6a12ffcc
generation 1 starts at 0x6a12ffc0
generation 2 starts at 0x016a1000
ephemeral segment allocation context: (0x6a12ffd8, 0x6a12ffe4)
 segment    begin allocated     size
016a0000 016a1000  0269ff64 0x00ffef64(16772964)
...

69130000 69131000  6a12ffd8 0x00ffefd8(16773080)
Large object heap starts at 0x026a1000
 segment    begin allocated     size
026a0000 026a1000  03698a98 0x00ff7a98(16743064)
...

70020000 70021000  70a7d750 0x00a5c750(10864464)
Total Size  0x3c67abb4(1013427124)
------------------------------
GC Heap Size  0x3c67abb4(1013427124)

Этого следует ожидать? Где будут оставшиеся ~ 500 МБ?

Еще немного деталей:

  • Сам файл дампа имеет размер 2.007.000.476 байт.
  • Машина, на которой было запущено программное обеспечение, имела только 1 ГБ физической оперативной памяти, но виртуальная память этой машины была настроена на увеличение до 3 ГБ (так что приложение должно иметь возможность увеличиваться до 1,5 ГБ максимум 32-битных приложений .net) .

person Evgeniy Berezovsky    schedule 28.09.2011    source источник


Ответы (2)


Скорее всего, процесс не знает 3 ГБ. Это настройка для каждого процесса.

Также, если вы хотите увидеть общее использование памяти, вы можете использовать !heap -s. Это даст вам сводную информацию о том, что делает каждая куча и сколько памяти она использует. Это также покажет вам проблемы с фрагментацией. Объедините это с управляемой кучей, и это должно дать вам представление об общем использовании памяти.

person Zipper    schedule 29.09.2011
comment
Процесс должен быть в состоянии подняться до 1,5G, если я не ошибаюсь. Моя проблема не в том, что я хочу изменить лимит (например, до 3 ГБ). Кстати. из других ответов/комментариев на SO у меня сложилось впечатление, что это даже невозможно. Я хочу знать, где остальные 500 мегабайт или около того, если не в куче .net. Я попробовал !heap -s, но это составило всего около 100 МБ (придется проверить еще раз позже, когда у меня будет больше времени, вывод этой команды требует некоторого привыкания) - person Evgeniy Berezovsky; 30.09.2011
comment
Вам нужно проверить размер резерва. Это в основном говорит вам, сколько адресного пространства процесса запросил процесс. Это высокое значение приведет к ошибкам OOM. Ну, это грубое упрощение, но это хорошее начало, и оно охватывает 90% случаев. - person Zipper; 04.10.2011

Размер дампа около 2 Гб указывает на то, что пользовательское адресное пространство процесса заполнено. Память заполняется не только выделениями памяти .Net, но и собственными (C/C++) выделениями, джиттинговым кодом, двоичными файлами, стеками и т. д. С помощью Windbg проверьте использование виртуального пространства с помощью !address -summary. Чтобы получить глобальное представление, вы также можете использовать DebugDiag для анализа дампа.

person plodoc    schedule 03.10.2011
comment
!address -summary говорит мне, что 1,917,264 КБ / ~ 98% Pct (Busy) используются RegionUsageIsVAD. Хотя не знаю, как это мне поможет. - person Evgeniy Berezovsky; 03.10.2011
comment
VAD — это память, выделенная через VirtualAlloc, не распознанная как кучи win32. Обычно память .Net и большие объекты из кучи Win32 помечаются как VAD. - person plodoc; 03.10.2011
comment
Вы смотрели на вывод !eeheap (без -gc), чтобы проверить память, используемую загрузчиком? - person plodoc; 03.10.2011