Может ли фрагментация кучи больших объектов вызвать OutOfMemory в 64-битных процессах?
Я готовлю презентацию для моей команды по.net GC и памяти. Различные источники обсуждают потенциальное влияние фрагментации на кучу больших объектов. Так как это было бы интересно показать, я пытаюсь показать это в коде.
Томас Веллер предложил этот код, который выглядит так, как будто он должен вызывать OOM при попытке выделить больший объект в освобожденные пробелы в LOH, но по какой-то причине этого не происходит. LOH автоматически сжимается в.net 4.6? Разве фрагментация LOH просто не проблема в 64-битной версии?
источник: /questions/12355839/fragmentatsiya-loh-obnovlenie-2015-goda/12355847#12355847
class Program
{
static IList<byte[]> small = new List<byte[]>();
static IList<byte[]> big = new List<byte[]>();
static void Main()
{
int totalMB = 0;
try
{
Console.WriteLine("Allocating memory...");
while (true)
{
big.Add(new byte[10*1024*1024]);
small.Add(new byte[85000-3*IntPtr.Size]);
totalMB += 10;
Console.WriteLine("{0} MB allocated", totalMB);
}
}
catch (OutOfMemoryException)
{
Console.WriteLine("Memory is full now. Attach and debug if you like. Press Enter when done.");
Console.WriteLine("For WinDbg, try `!address -summary` and `!dumpheap -stat`.");
Console.ReadLine();
big.Clear();
GC.Collect();
Console.WriteLine("Lots of memory has been freed. Check again with the same commands.");
Console.ReadLine();
try
{
big.Add(new byte[20*1024*1024]);
}
catch(OutOfMemoryException)
{
Console.WriteLine("It was not possible to allocate 20 MB although {0} MB are free.", totalMB);
Console.ReadLine();
}
}
}
}
2 ответа
Начиная с.NET 4.5.1 (также.NET Core) поддерживается сжатие LOH, и поведение может быть установлено GCSettings.LargeObjectHeapCompactionMode
свойство статического класса GcSettings.
Это означает, что LOH уплотнен GC.
Имейте в виду, что 32-битный процесс имеет некоторые ограничения на объем используемой памяти, поэтому он с большей вероятностью столкнется с исключением OOM.
Я думаю, что LOH не будет компактным автоматически.
Поскольку компактный LOH влияет на производительность, мы должны делать это, когда знаем это наверняка.
С этим кодом он скоро исчерпает память, компактное действие только перезаписывает объект, на который не ссылаются