LOH fragmentation - 2015 update

馋奶兔 提交于 2019-11-27 09:23:05

The change from 12 to 24 in the byte[] example can be explained by the change in CPU architecture from 32 to 64 bit. In programs compiled for x64 or AnyCPU, the .NET overhead increases from 2*4 bytes (4 bytes Object Header + 4 bytes Method Table) to 2*8 bytes (8 bytes Object Header + 8 bytes Method Table). In addition, the array has a length property of 4 bytes (32 bit) versus 8 bytes (64 bits).

For the double[] example, just use a calculator: 85000 bytes / 64 bit for the double type = 10625 items, which is already close. Considering the .NET overhead, the result is (85000 bytes - 24 bytes) / 8 bytes per double = 10622 doubles. So there is no special handling of double[] any more.

BTW, I have never found any working demonstration for LOH fragmentation before, so I wrote one myself. Just compile the following code for x86 and run it. It even includes some debugging hints.

It won't work as well when compiled as x64 since Windows might increase the size of the pagefile, so the subsequent allocation of 20 MB memory could be successful again.

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();
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!