我想弄清楚为什么我们的某个网站使用2.3GB内存。从windbg开始,当我运行!dumpheap -stat
时,我得到了这个:
000007fe992ae8d8 39413 11489246 System.Byte[]
000007fe992abf40 8567 14995548 System.Char[]
000007fe994500b0 31763 31617136 System.Int32[]
000007fe9c7b4cf8 1221470 48858800 XXXXXXX.SearchService+SectorItem
000007fe9925ba30 219828 49646032 System.Object[]
000007fe992a46f0 4273039 264621916 System.String
0000000002a35c10 2214 923713198 Free
Total 6994094 objects
Fragmented blocks larger than 0.5 MB:
Addr Size Followed by
000000010625ef50 1.2MB 00000001063982e0 System.Collections.Hashtable
00000001064c9ed0 4.4MB 0000000106932128 System.Object[]
0000000206a4ee48 0.6MB 0000000206ae0a10 System.String
0000000206d270a0 3.9MB 0000000207106058 Free
0000000305282098 0.8MB 000000030534d248 System.Xml.XmlElementListListener
00000003053c5ad0 0.9MB 00000003054a87c0 System.String
0000000406a8b0f0 1.9MB 0000000406c73f10 System.WeakReference
0000000406c7aac8 2.2MB 0000000406ea43a8 System.Byte[]
0000000406ef89a8 1.5MB 00000004070721d8 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.String, mscorlib],[System.DateTime, mscorlib]]
0000000407072208 1.2MB 00000004071a77c0 System.Threading.ThreadPoolWorkQueueThreadLocals
00000004073d1110 11.3MB 0000000407f1a7f8 Free
我们可以看到有超过900MB的“免费”对象,并且从未从IIS内存中释放(因为我看了几天的图表)。如果我这样做,有2200个免费对象:
!dumpheap -mt 0000000002a35c10
有很多免费物品:
00000005310b8008 0000000002a35c10 30 Free
00000005310dce28 0000000002a35c10 30 Free
0000000531101a50 0000000002a35c10 30 Free
0000000531126870 0000000002a35c10 30 Free
000000053114c680 0000000002a35c10 30 Free
0000000531187ee8 0000000002a35c10 30 Free
00000005311c3538 0000000002a35c10 30 Free
00000005311fefe0 0000000002a35c10 18583286 Free
0000000532a5e3a0 0000000002a35c10 9499822 Free
0000000533383848 0000000002a35c10 9830638 Free
0000000533d98db8 0000000002a35c10 46462326 Free
0000000536a40d70 0000000002a35c10 30 Free
0000000536a6f300 0000000002a35c10 10549646 Free
00000005374cf138 0000000002a35c10 10246582 Free
0000000537ee4f98 0000000002a35c10 80664406 Free
000000053cccb570 0000000002a35c10 22118654 Free
根据这篇文章: https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/ 大于85000bytes的任何内容都不会自动重新收集。 那么我可以得出结论,我们在内存中有一些非常大的对象(例如,可能是一个大字典)并且永远不会被GC删除吗?那么除了内存泄漏问题外,这是一个LOH问题吗?
如果是LOH问题,如果大对象在Cache中(如此重用)或在内存中使用一次会有什么不同吗? GC会收集其中任何一个吗?
答案 0 :(得分:0)
任何大于85000bytes的内容都不会自动重新收集。
它将被收集,但它不会包含在GC堆的压缩中。
所以我可以得出结论,我们在内存中有一些非常大的对象[...]
不是来自给定的数据。如果两个Free
区域相互跟随,则它们将组合成一个更大的区域。因此,9 MB Free
区域可能是1000个“小”对象,每个对象9000字节,随后在内存中对齐。
[...]并且永远不会被GC删除?
它们已被GC删除,因为它是Free
。这些不是Free
类型的对象。从.NET的角度来看它确实是免费的,当你创建新对象时它将被.NET框架重用。
但是,使用VirtualFree()
调用,该内存尚未从.NET返回到操作系统。因此,从OS的角度来看,内存仍在使用中。
所以这是一个LOH问题[...]
如果不知道GC堆的边界,就不可能分辨出来。尝试!eeheap
查看代数的开始位置或使用SOSEX“!dumpgen
转储特定的GC堆,以查看它是否包含Free
个对象。
[...]除了内存泄漏问题?
这不是内存泄漏,因为内存已被垃圾收集器释放。您的开发人员无法做很多事情来使.NET将该内存返回给操作系统。出于某种原因,.NET认为它应该保留内存供以后使用。
如果大对象在Cache中(如此重用)或在内存中使用过一次会有什么不同吗?
如果它被缓存引用,则该对象不会被垃圾收集(如果它不是弱引用)。然后,您将不再看到Free
个对象,而是真正的对象。
GC会收集其中任何一个吗?
GC将收集未引用的对象,并可能收集弱引用引用的对象(缓存可能使用的对象)。