управляемая фрагментация кучи - PullRequest
10 голосов
/ 24 июня 2011

Я пытаюсь понять, как работает фрагментация кучи. Что говорит мне следующий вывод?

Чрезмерно фрагментирована эта куча?

У меня 243010 «свободных объектов» с общим объемом 53304764 байта. Являются ли те пространства «свободных объектов» в куче, которые когда-то содержали объекты, но которые теперь собираются мусором?

Как заставить очистить фрагментированную кучу?

!dumpheap -type Free -stat
total 243233 objects
Statistics:
      MT    Count    TotalSize Class Name
0017d8b0   243010     53304764      Free

Ответы [ 2 ]

7 голосов
/ 02 июля 2011

Это зависит от того, как организована ваша куча.Вы должны посмотреть, сколько памяти в Gen 0,1,2 выделено и сколько у вас там свободной памяти по сравнению с общим объемом используемой памяти.Если у вас есть 500 МБ управляемой кучи, но 50 МБ свободно, значит, у вас все хорошо.Если вы выполняете операции с интенсивным использованием памяти, например, создаете много элементов управления WPF и освобождаете их, вам понадобится намного больше памяти в течение короткого времени, но .NET не возвращает память ОС после того, как вы ее выделили.ГХ пытается распознать шаблоны распределения и имеет тенденцию поддерживать высокий объем занимаемой памяти, хотя текущий размер кучи слишком велик, пока на вашей машине не заканчивается физическая память.

Я обнаружил, что гораздо проще использовать psscor2 для .NET 3.5, в котором есть несколько интересных команд, таких как ListNearObj , где вы можете узнать, какие объекты находятся вокруг дыр в вашей памяти (закрепленные объекты?).С помощью команд из psscor2 у вас гораздо больше шансов узнать, что на самом деле происходит в ваших кучах.Большинство команд также доступно в SOS.dll в .NET 4.

Чтобы ответить на ваш первоначальный вопрос: Да, свободные объекты - это пробелы в управляемой куче, которые могут просто быть свободным блоком памяти после вашего последнего выделенного объекта.на участке GC.Или, если вы сделаете! DumpHeap с начальным адресом сегмента GC, вы увидите объекты, размещенные в этом сегменте управляемой кучи, вместе с вашими свободными объектами, которые являются объектами, собранными GC.

Эти дыры в памяти обычно происходят в Gen2.Адреса объектов до и после свободного объекта сообщают вам, какие потенциально закрепленные объекты находятся вокруг вашей дыры.Исходя из этого, вы сможете определить свою историю распределения и оптимизировать ее, если вам нужно.Вы можете найти адреса кучи GC с помощью

0:021> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x101da9cc
generation 1 starts at 0x10061000
generation 2 starts at 0x02aa1000
ephemeral segment allocation context: none
 segment     begin allocated  size
02aa0000  02aa1000**  03836a30  0xd95a30(14244400)
10060000  10061000**  103b8ff4  0x357ff4(3506164)
Large object heap starts at 0x03aa1000
 segment     begin allocated  size
03aa0000  03aa1000  03b096f8  0x686f8(427768)
Total Size:              Size: 0x115611c (18178332) bytes.
------------------------------
GC Heap Size:            Size: 0x115611c (18178332) bytes.

Там вы видите, что у вас есть кучи по 02aa1000 и 10061000. С помощью! DumpHeap 02aa1000 03836a30 вы можете сбросить сегмент кучи GC.

!DumpHeap 02aa1000  03836a30  
    Address  MT             Size
    ...
    037b7b88 5b408350       56     
    037b7bc0 60876d60       32     
    037b7be0 5b40838c       20     
    037b7bf4 5b408350       56     
    037b7c2c 5b408728       20     
    037b7c40 5fe4506c       16     
    037b7c50 60876d60       32     
    037b7c70 5b408728       20     
    037b7c84 5fe4506c       16     
    037b7c94 00135de8   519112 Free
    0383685c 5b408728       20     
    03836870 5fe4506c       16     
    03836880 608c55b4       96   
    ....

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

0 голосов
/ 30 июня 2011

У вас есть 50 МБ ОЗУ в качестве свободного места.Это нехорошо.

Имея .NET, выделяющие из процесса блоки по 16 МБ, мы действительно имеем проблему фрагментации.Существует множество причин фрагментации в .NET.

Посмотрите здесь и здесь .В вашем случае это, возможно, пиннинг.Поскольку 53304764/243010 составляет 219,35 байта на объект - намного ниже, чем объекты LOH.

...