[英]How to Solve Gen2 Heap Fragmentation
I am running a C# application that services HTTP requests. 我正在运行一个为HTTP请求提供服务的C#应用程序。 I have noticed recently that it's taking up more memory then I expect.
我最近注意到它占用的内存比我预期的多。 I grabbed some dumps, popped them in Windbg, and found that most of the memory was marked as Free:
我抓住了一些转储,在Windbg中弹出它们,发现大部分内存被标记为Free:
!dumpheap -stat
...
00007ffde4783630 681599 65433504 System.Threading.Tasks.TaskFactory+CompleteOnInvokePromise
00007ffde47cc988 167885 76872908 System.Byte[]
00007ffde47c6948 521353 80352802 System.String
0000007e3a16c2d0 1870425 1415374334 Free
So the dump is ~3GB so about half of it is free memory. 所以转储大约3GB,所以大约一半是免费内存。 Looking at the heaps I see this:
看着堆,我看到了这个:
!heapstat
Heap Gen0 Gen1 Gen2 LOH
Heap0 82248472 7354560 987275056 178834656
Heap1 93146552 6382864 857470096 129435960
Total 175395024 13737424 1844745152 308270616
Free space: Percentage
Heap0 40969256 146456 640426720 54829792 SOH: 63% LOH: 30%
Heap1 75943736 94448 550812312 54825216 SOH: 65% LOH: 42%
Total 116912992 240904 1191239032 109655008
So the my small object heaps are very fragmented, specifically Gen2. 所以我的小物件堆很碎片,特别是Gen2。 On the server I can see that gen2 collections are happening (using performance counters) but even though they are the it looks like the gen2 heap is not being compacted.
在服务器上我可以看到gen2集合正在发生(使用性能计数器),但即使它们看起来像gen2堆也没有被压缩。 Even when there is only 1-2% of RAM available on the server the gen2 heap is not being compacted.
即使服务器上只有1-2%的RAM可用,也不会压缩gen2堆。
To me it looks like I am suffering this memory pressure because the heap is fragmented. 对我来说,看起来我正在遭受这种记忆压力,因为堆是碎片。 However I can't figure out why the fragmentation is happening or why gen2 is unable to be compacted.
但是我无法弄清楚为什么碎片化正在发生或为什么gen2无法被压缩。 Some of the free spaces are 6MB in size so I would think it would for sure compact those spaces away.
一些自由空间的大小是6MB,所以我认为它肯定会压缩那些空间。
Can anyone give me some ideas on how to figure out why my heap is so fragmented? 任何人都可以给我一些关于如何弄清楚为什么我的堆如此碎片化的想法? Am I even barking up the right tree here?
我甚至在这里咆哮着正确的树吗?
Any help will be greatly appreciated, thanks! 任何帮助将不胜感激,谢谢!
EDIT 1: 编辑1:
The breakdown of !gchandles
is: !gchandles
的细分是:
Handles:
Strong Handles: 4507
Pinned Handles: 58
Async Pinned Handles: 977
Ref Count Handles: 1
Weak Long Handles: 6087
Weak Short Handles: 724
The next step would be to use !gchandles
and look for pinned handles. 下一步是使用
!gchandles
并寻找固定手柄。 This might identify objects that are locked to a specific memory position, because some native code (eg C++) needs to access it. 这可能会识别锁定到特定内存位置的对象,因为某些本机代码(例如C ++)需要访问它。 While garbage colelction may move objects around in memory, the C++ pointer will not be updated by .NET, so pinning is the only option.
虽然垃圾收集可能会在内存中移动对象,但.NET不会更新C ++指针,因此固定是唯一的选择。
Even when there is only 1-2% of RAM available on the server the gen2 heap is not being compacted.
即使服务器上只有1-2%的RAM可用,也不会压缩gen2堆。
You're talking about physical RAM here. 你在这里谈论物理RAM。 From an operating system, I expexct that it uses the available resources as good as possible, so I expect the RAM to be 100% used at all the time.
从操作系统来看,我认为它尽可能使用可用资源,所以我希望 RAM始终100%使用。 If it is "not used", I expect the OS to use it for caching.
如果它“未使用”,我希望操作系统将其用于缓存。 Due to this, the physical RAM usage cannot really be an indicator for garbage collection.
因此,物理RAM使用不能真正成为垃圾收集的指标。
Also, I would not worry too much. 另外,我不会太担心。 If the memory is not used by .NET, it will be swapped to disk by the OS and thus free physical RAM for other purposes.
如果.NET未使用该内存,则它将由操作系统交换到磁盘,从而将其用于其他目的的物理RAM。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.