c# - 如何解决 Gen2 堆碎片

标签 c# .net garbage-collection memory-fragmentation heap-fragmentation

我正在运行一个为 HTTP 请求提供服务的 C# 应用程序。我最近注意到它占用的内存比我预期的要多。我抓取了一些转储,将它们弹出到 Windbg 中,发现大部分内存都标记为空闲:

!dumpheap -stat
...
00007ffde4783630   681599     65433504 System.Threading.Tasks.TaskFactory+CompleteOnInvokePromise
00007ffde47cc988   167885     76872908 System.Byte[]
00007ffde47c6948   521353     80352802 System.String
0000007e3a16c2d0  1870425   1415374334      Free

因此转储约为 3GB,其中大约一半是可用内存。看着堆,我看到了这个:

!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

所以我的小对象堆非常零散,特别是 Gen2。在服务器上,我可以看到 gen2 收集正在发生(使用性能计数器),但即使它们是 gen2 堆看起来也没有被压缩。即使服务器上只有 1-2% 的 RAM 可用,gen2 堆也不会被压缩。

对我来说,我似乎正在承受这种内存压力,因为堆是碎片化的。但是我无法弄清楚为什么会发生碎片化或者为什么 gen2 无法压缩。一些可用空间的大小为 6MB,因此我认为它肯定会压缩这些空间。

谁能给我一些关于如何弄清楚为什么我的堆如此碎片化的想法?我什至在这里咆哮正确的树吗?

任何帮助将不胜感激,谢谢!

编辑 1:

!gchandles 的分解是:

Handles:
Strong Handles:       4507
Pinned Handles:       58
Async Pinned Handles: 977
Ref Count Handles:    1
Weak Long Handles:    6087
Weak Short Handles:   724

最佳答案

下一步是使用 !gchandles 并查找固定句柄。这可能会识别锁定到特定内存位置的对象,因为某些 native 代码(例如 C++)需要访问它。虽然垃圾回收可能会在内存中移动对象,但 C++ 指针不会被 .NET 更新,因此固定是唯一的选择。

Even when there is only 1-2% of RAM available on the server the gen2 heap is not being compacted.

您在这里谈论的是物理 RAM。对于操作系统,我希望它尽可能好地使用可用资源,所以我希望 RAM 始终被 100% 使用。如果它“未使用”,我希望操作系统将它用于缓存。因此,物理 RAM 使用率不能真正成为垃圾收集的指标。

另外,我不会太担心。如果内存未被 .NET 使用,操作系统会将其交换到磁盘,从而释放物理 RAM 用于其他目的。

关于c# - 如何解决 Gen2 堆碎片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47480337/

相关文章:

c# - 从 .NET 以编程方式访问 "Open with"Windows 资源管理器菜单列表

java - 其元素的通用实例化的 Java 数组的包装器类

c# - 如何从 C# 中的简单数组中获取元素?

c# - 为什么包含 ValueTuple 的结构可以满足非托管约束,而 ValueTuple 本身却不能?

c# - VS中有类似大纲 View 的东西吗?

c++ - 使用 AutoZone 垃圾收集器

java - 最快次要GC的收集器

c# - Quickfixn SSL 配置问题

c# - linq 按日期时间列上的开始时间到结束时间分组

c# - OpenPop.net 获取实际消息文本