很多文章都谈到大于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数组或字符串.
浙公网安备 33010602011771号