Бесплатные объекты ~ 50% кучи .NET. Как узнать, что вызывает OOM

Я пытаюсь определить, что способствует использованию большого объема памяти моим приложением. Итак, я взял файл дампа процесса. Команда EEHeap показывает около 2,8 ГБ в куче памяти .NET.

0:000> !EEHeap -gc
Number of GC Heaps: 2
------------------------------
Heap 0 (00000000001e3030)
generation 0 starts at 0x00000000a5f21360
generation 1 starts at 0x00000000a5c45a60
generation 2 starts at 0x000000007fff1000
ephemeral segment allocation context: none
 segment     begin allocated  size
000000007fff0000  000000007fff1000  00000000beeca248  0x3eed9248(1055756872)
Large object heap starts at 0x000000027fff1000
 segment     begin allocated  size
000000027fff0000  000000027fff1000  000000028f7d42f8  0xf7e32f8(259928824)
Heap Size:               Size: 0x4e6bc540 (1315685696) bytes.
------------------------------
Heap 1 (00000000001ed9e0)
generation 0 starts at 0x00000001a6c77908
generation 1 starts at 0x00000001a69a8370
generation 2 starts at 0x000000017fff1000
ephemeral segment allocation context: none
 segment     begin allocated  size
000000017fff0000  000000017fff1000  00000001cc127e58  0x4c136e58(1276341848)
Large object heap starts at 0x000000028fff1000
 segment     begin allocated  size
000000028fff0000  000000028fff1000  000000029b55d8f8  0xb56c8f8(190236920)
Heap Size:               Size: 0x576a3750 (1466578768) bytes.
------------------------------
GC Heap Size:            Size: 0xa5d5fc90 (2782264464) bytes.

Странно то, что самая большая запись для !Dumpheap - это бесплатный, который занимает ~ 1,3 ГБ

00000000001ac980      388   1373069656      Free

Некоторые из них находятся в LOH.

0:000> !dumpgen 3 -stat
       Count      Total Size      Type
-------------------------------------------------
           2        233,376   System.Collections.Hashtable+bucket[]
           1        262,168   System.Double[]
           6      1,804,496   System.Int64[]
           1      1,868,972   System.Int32[]
          57     18,707,978   System.Byte[]
          31     69,830,576   System.Object[]
         102    346,151,516   **** FREE ****

Нет готовых к финализации объектов, что говорит мне, что поток Finalize только что завершил свою работу.

0:000> !FinalizeQueue
SyncBlocks to be cleaned up: 0
Free-Threaded Interfaces to be released: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
------------------------------
Heap 0
generation 0 has 2748 finalizable objects (00000000047b6518->00000000047bbaf8)
generation 1 has 55 finalizable objects (00000000047b6360->00000000047b6518)
generation 2 has 6878 finalizable objects (00000000047a8c70->00000000047b6360)
Ready for finalization 0 objects (00000000047bbaf8->00000000047bbaf8)
------------------------------
Heap 1
generation 0 has 69 finalizable objects (0000000004807160->0000000004807388)
generation 1 has 6 finalizable objects (0000000004807130->0000000004807160)
generation 2 has 7818 finalizable objects (00000000047f7ce0->0000000004807130)
Ready for finalization 0 objects (0000000004807388->0000000004807388)

LOH кажется сильно фрагментированным.

0:000> !HeapStat
Heap             Gen0         Gen1         Gen2          LOH
Heap0       419073768      2996480    633686624    259928824
Heap1       625673552      2946456    647721840    190236920
Total      1044747320      5942936   1281408464    450165744

Free space:                                                 Percentage
Heap0       397468560           24      1545984    183287672SOH: 37% LOH: 70%
Heap1       611153984           24     16750104    162864048SOH: 49% LOH: 85%
Total      1008622544           48     18296088    346151720

Я не знаю, соединяю ли я здесь все точки, но я думаю, что в следующем GC весь свободный объект будет удален из памяти, а память кучи .NET должна снизиться на основе бесплатных объектов, которые находятся в Gen 0, 1, 2 (потому что они будут сжаты). Это справедливое заявление, или вы видите какие-либо другие проблемы, которые я могу упустить? Конечно, фрагментация LOH - это проблема, но я не знаю, насколько это влияет на использование приложений.

РЕДАКТИРОВАТЬ: Applicaton теперь не работает с OOM. Основываясь на некоторых комментариях ниже, память, указанная для объекта Free, не возвращается в ОС. Как я могу узнать, что вызывает OOM


person crazy novice    schedule 02.03.2015    source источник
comment
все свободные объекты будут удалены из памяти - нет, они уже являются свободной памятью и останутся такими. Вы не можете удалить то, чего больше нет.   -  person Henk Holterman    schedule 02.03.2015
comment
но мой процесс вернет это свободное пространство при сжатии памяти (кроме LOH)?   -  person crazy novice    schedule 02.03.2015
comment
Он уже вернулся. Не совсем понятно, о чем вы спрашиваете, возможно, вам стоит прочитать этот вопрос   -  person Henk Holterman    schedule 02.03.2015
comment
То есть объект, помеченный как Свободный (в эфермальных сегментах), не будет уплотнен?   -  person crazy novice    schedule 02.03.2015
comment
Вы все равно должны четко понимать, что, по вашему мнению, это означает. Как говорится в принятом ответе на ссылку, это виртуальная память, и это (обычно) не имеет значения. У вас действительно есть проблема, например, исключения OOM?   -  person Henk Holterman    schedule 03.03.2015
comment
Нет OOM, но использование памяти приложения велико, и когда я увидел, что ~ 50% памяти находится в этих Free объектах, я подумал, что это то, что GC требует обратно во время сжатия GC.   -  person crazy novice    schedule 03.03.2015
comment
На самом деле начните получать OOM сейчас, тогда как шаблоны памяти остаются такими же, где бесплатные объекты используют 50% кучи .NET.   -  person crazy novice    schedule 04.03.2015


Ответы (1)


Куча больших объектов не выполняет автоматическую дефрагментацию, поэтому действительно можно получить OOM, пока у вас много свободного места на LOH. Из этой ямы нет простого выхода. Есть три общих подхода:

1) Уменьшите количество выделений LOH (> 85 000 байт), выполняемых вашим приложением, объедините большие объекты вместо того, чтобы позволять им собираться, и попытайтесь выполнить небольшое количество очень больших распределений вместо большого количества средних.

2) Используйте .NET 4.5. LOH уплотнение .1. Это временный промежуток, а не истинное решение, но если фрагментация - единственная проблема, связанная с памятью, которая у вас есть, это может помочь на данный момент.

3) Перейти к 64-битному процессу. У вас по-прежнему будет проблема фрагментации, но у вас не будет так легко закончиться память.

person Sasha Goldshtein    schedule 23.07.2015