导航

用windbg来发现哪些对象可以分配到LOH上(Large object heap)

Posted on 2008-08-14 22:59  BitsBlue  阅读(2273)  评论(3)    收藏  举报

很多文章都谈到大于85,000字节的对象会放在LOH上. 但问题是如果一个对象包含了一个很大的字节数组或者一个huge字符串, 这种情况下到底是对象本身被分配到LOH还是被包含的字节数组或字符串呢? 最简单的方式,打开windbg来自己看看就知道了.

 

测试代码如下:

    class BigObj1
    {
        public byte[] BigArray = new byte[90000];
    }

    class BigObj2
    {
        public string BigString = new string('a', 45000);
    }

    class Program
    {
        static void Main(string[] args)
        {
            BigObj1 b1 = new BigObj1();
            BigObj2 b2 = new BigObj2();

            Console.Read();

            Console.WriteLine(b1.ToString());
            Console.WriteLine(b2.ToString());

        }
    }

 

用windbg来run程序并且加载sos来观察.

 

0:003> ~0s (切换到main thread)

 

0:000> !dso (打印出stack 里面的objects)
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0x1240 (0)
ESP/REG  Object   Name
002ef04c 01de1760 Microsoft.Win32.SafeHandles.SafeFileHandle
002ef05c 01de1760 Microsoft.Win32.SafeHandles.SafeFileHandle
002ef090 01de2938 System.Byte[]
002ef094 01de1774 System.IO.__ConsoleStream
002ef0b8 01de172c Moq.BigObj2
002ef0bc 01de28e0 System.IO.StreamReader
002ef0c0 01de1720 Moq.BigObj1
002ef0d0 01de172c Moq.BigObj2
002ef0d4 01de28e0 System.IO.StreamReader
002ef0d8 01de1720 Moq.BigObj1
002ef0e0 01de2c54 System.IO.TextReader+SyncTextReader
002ef0e8 01de172c Moq.BigObj2
002ef0f4 01de1710 System.Object[]    (System.String[])
002ef1b4 01de1710 System.Object[]    (System.String[])
002ef368 01de1710 System.Object[]    (System.String[])
002ef390 01de1710 System.Object[]    (System.String[])

0:000> !objsize 01de1720 (object size of BigObj1)
sizeof(01de1720) =        90024 (     0x15fa8) bytes (Mo

0:000> !objsize 01de172c (object size fo BigObj2)
sizeof(01de172c) =        90032 (     0x15fb0) bytes (Moq.BigObj2)q.BigObj1)
看来这两个对象确实很大,应该够进LOH了.

 

0:000> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x01de1018
generation 1 starts at 0x01de100c
generation 2 starts at 0x01de1000
ephemeral segment allocation context: none
 segment    begin allocated     size
00486c58 790d8620  790f7d8c 0x0001f76c(128876)
01de0000 01de1000  01de3ff4 0x00002ff4(12276)
Large object heap starts at 0x02de1000
 segment    begin allocated     size
02de0000 02de1000  02e0ef98 0x0002df98(188312)
Total Size   0x506f8(329464)
------------------------------
GC Heap Size   0x506f8(329464)

 

0:000> !dumpheap -stat 02de1000 02e0ef98 (限定开始和结束地址来打印出在LOH上的objects)
total 9 objects
Statistics:
      MT    Count    TotalSize Class Name
0047b470        5           80      Free
7912d8f8        2         8192 System.Object[]
7912dae8        1        90016 System.Byte[]
790fd8c4        1        90024 System.String
Total 9 objects

 

结果看起来只有字节数组和字符串进了LOH,而BigObj1和BigObj2都没有. 如果一个复杂对象包含A另外一个复杂对象B然后复杂对象B包含一个大数组, 到底是谁进LOH呢? 答案应该显而易见, 读者可自行校验.

 

结论:

不要被大于85,000字节的对象分配到LOH迷惑了,真正进入LOH的是那些被包含的大的简单类型或object数组或字符串.