大对象堆碎片可以在64位进程中导致OutOfMemory吗?

时间:2018-01-16 12:55:40

标签: c# .net memory garbage-collection large-object-heap

我正准备在.net GC和内存上向我的团队做一个演示。 不同的来源讨论了碎片对大型物体堆的潜在影响。 由于这将是一个有趣的现象,我试图在代码中显示。

托马斯·韦勒提供了这样的代码,当试图将更大的对象分配到LOH中释放的空隙时,它看起来应该导致OOM,但由于某种原因它不会发生。 LOH是否在.net 4.6中自动压缩? LOH碎片在64位中根本不是问题吗?

来源:https://stackoverflow.com/a/30361185/3374994

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 个答案:

答案 0 :(得分:2)

由于.NET 4.5.1(也是.NET Core)支持LOH压缩,并且行为可以由静态类GcSettingsGCSettings.LargeObjectHeapCompactionMode属性设置。

这意味着,GC已经压缩了LOH

请注意,32位进程对可以使用的内存有一些限制,因此更有可能遇到OOM异常。

答案 1 :(得分:1)

我的猜测是,LOH不会自动紧凑。

由于紧凑的LOH对性能的影响,我们应该在我们确切知道的时候这样做。

使用此代码,它将很快耗尽内存,紧凑操作仅回收未引用的对象