第0代堆内存在较大差距

时间:2018-05-02 09:07:20

标签: c# .net memory-leaks garbage-collection memory-profiling

我目前正在调查内存泄漏,我无法解释,现在我正在寻找有用的链接或想法。

以下是应用程序本机内存的屏幕截图(使用.NET内存分析器创建):

enter image description here

应用程序大约需要2.2 GB(这是正常的)。当应用程序大约3.5 GB时,转储被占用。而这一代#0中的这些差距是我目前无法解释的。对我来说,似乎垃圾收集器并没有压缩第0代的差距。

为了有一个明确的问题:

  • 这些差距是如何发生的?对我来说,这似乎是因为GC收集了死对象但没有压缩堆。我知道我无法触发或强制GC压缩堆。

我在这个网站上搜索过类似的问题,但其中大部分是关于LOH的(在我的情况下似乎很好)。唯一存在某种类似大差距的问题是:What are GC Holes,但我无法看到2 KB的第0代固定实例如何产生1 GB的漏洞。另一个问题是关于触发GC GC thresholds的阈值。但我无法相信没有单一的压实阶段。

2 个答案:

答案 0 :(得分:1)

孔/间隙表示两个已分配实例之间未使用的内存。当堆未完全压缩时(由于垃圾收集器中的固定实例或优化),会出现“漏洞”。

您无法显式压缩堆本身。但是,GC有时可以执行完整或部分收集。

所以你有差距,这是什么意思?这意味着分配到堆更复杂,你可以做些什么......不是很多。如果它是性能问题,你可以稍微使用GC。但是,如果你使用大量固定内存,那么你无能为力。这称为碎片

其他资源

Garbage Collector Basics and Performance Hints

What are GC holes?

GC behavior when pinning an object

What causes memory fragmentation in .NET

No More Memory Fragmentation on the .NET Large Object Heap

答案 1 :(得分:0)

直到今天,我仍然不确定到底是什么引起了这个问题,但是已经通过这种方式解决了。首先,我有一些Windows Dumps和NMP Dumps,并在其中做了很多准备(WinDBG很有帮助)。在那里,我发现某些数据与套接字有关。

因此,唯一的办法就是将当前的套接字实现从Begin *调用重写为* Async调用。 (请参阅this question

我们跟随msdn implementation。 (创建一个大缓冲区并重用它)。特别是那里的评论指向那个方向:

    // Allocates one large byte buffer which all I/O operations use a piece of.  This gaurds 
    // against memory fragmentation

差距现在没有消除,但差距越来越小,而且不再增长...