简体   繁体   English

如何解决Gen2堆碎片问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM