《Advanced .NET Debugging》 读书笔记 Listing 5-8: Fragmentation的简单示例

程序如下:

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace Advanced.NET.Debugging.Chapter5
{
    class Fragment
    {
        static void Main(string[] args)
        {
            Fragment f = new Fragment();
            f.Run(args);
        }

        public void Run(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("05Fragment.exe <alloc. size> <max mem in MB>");
                return;
            }

            int size = Int32.Parse(args[0]);
            int maxmem = Int32.Parse(args[1]);
            byte[][] nonPinned = null;
            byte[][] pinned = null;
            GCHandle[] pinnedHandles = null;

            int numAllocs = maxmem * 1000000 / size;

            pinnedHandles = new GCHandle[numAllocs];

            pinned = new byte[numAllocs / 2][];
            nonPinned = new byte[numAllocs / 2][];

            for (int i = 0; i < numAllocs / 2; i++)
            {
                nonPinned[i] = new byte[size];
                pinned[i] = new byte[size];
                pinnedHandles[i] =
           GCHandle.Alloc(pinned[i], GCHandleType.Pinned);
            }

            Console.WriteLine("Press any key to GC & promo to gen1");
            Console.ReadKey();

            GC.Collect();

            Console.WriteLine("Press any key to GC  & promo to gen2");
            Console.ReadKey();

            GC.Collect();

            Console.WriteLine("Press any key to GC(free non pinned");
            Console.ReadKey();

            for (int i = 0; i < numAllocs / 2; i++)
            {
                nonPinned[i] = null;
            }

            GC.Collect();

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

程序的关键就是GCHandle.Alloc这一句,可见在这一个for循环语句内,交替为pinned[]数组设置了Pinned类型的句柄,而nonPinned[]数组没有这种句柄。一旦设置以后,这样的对象在heap中不能移动位置。由于交替设置了nonPinned数组,所以会在Pinned数组元素的中间出现未利用的内存块,从而形成fragmentation。

1. 在命令行工具里执行 05fragment.exe 50000 1000  这个语句的意思是,分配1G大小的内存空间,每个数组的大小为50kB。

2. 打开WinDbg,attach到这个进程上。

3. 执行 .loadby sos.dll mscorwks

4. 执行 !DumpHeap –stat ,可见到此时内存分配的状况:

image

由于free的内存空间所占大小与heap总体积相比非常小,所以可以认为不存在fragment的问题。

5. 让程序继续运行,直到提示按任意键退出的时候,进入WinDbg,执行 !dumpheap –stat:

image

可见此时未利用的内存块的大小已经占到了heap的一半大小,此时fragment发生了。

posted on 2011-01-08 13:19  李志鹏  阅读(205)  评论(0)    收藏  举报

导航