服务器模式 GC 似乎从不收集 Gen 0 堆

2023-11-22

澄清的问题(tl;dr)

在阅读并分析了下面涵盖的所有结果后,问题似乎归结为 GC 在服务器模式下没有为我们的应用程序收集 Gen 0 堆,一旦更改为工作站模式,问题就会消失。

原始问题和详细信息

我的问题与以下内容有些相关:这个问题 and 这个问题.

最近,我们在测试环境中的 .NET 应用程序中遇到了内存泄漏问题,工作进程在负载情况下会迅速攀升至 450MB 左右,在无负载情况下会逐渐攀升至 450MB 左右。

该问题无法在我们的开发环境中复制,主要区别在于开发环境是物理服务器,而测试环境是虚拟化的并由 Puppet 控制(除此之外,我对环境本身了解不多)。

为了希望了解哪些对象占用了所有内存,我在测试服务器上运行了 Ants Memory Profiler,发现所有内存都未使用且从未被释放。

在研究可能导致此问题的原因时,我遇到了这个论坛帖子这又让我本文.

我最终尝试了它推荐的配置,将 GC 置于工作站模式:

<configuration>
  <runtime>
    <gcServer enabled="false"/>
    <gcConcurrent enabled="false"/>
  </runtime>
</configuration>

运行 iisreset 并重新运行内存分析后,问题完全消失了,这很好,但仍然不能真正解释最初发生的情况。

我确实做了更多阅读并发现这个问题,这让我相信这种配置更改最终可能会损害我们应用程序的吞吐量。

所以我的问题是:什么会导致 IIS 工作进程积累大量未使用的内存,而这些内存永远不会被垃圾收集?

Edit:为了进一步澄清我的问题,我相信我们已经证明代码对此不负有责任,因为完全相同的代码在开发环境中不会遇到此问题。

这是我在配置更改之前和之后的内存分析的屏幕截图,这里没有太多信息,但该图确实很好地显示了内存趋势。

Before Configuration Change After Configuration Change

Edit 2:以下是我能收集到的服务器规格,我可能会得到更多,只是需要时间。

开发环境: 物理机 CPU:单核 内存:6GB

测试环境: 虚拟机 CPU:4 个逻辑线程(我无法评论 CPU 数量) 内存:8GB

Machine.Config 文件中的唯一区别是开发环境添加 “Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior”到端点和服务行为。

并且测试环境当前具有前面在aspnet.config文件中提到的GC设置。

Edit 3:进行了更多分析,发现我可以在 Ants 中添加更多计数器,特别是我添加了“Gen 0 堆大小”,看起来这就是问题的根源。当 GC 处于服务器模式时,当我触发我用于分析的测试时,这条线立即跳到 ~300MB,然后回落到 ~230MB,但永远不会一路回落(下图)。

Gen 0 Before

在工作站模式下使用 GC 运行相同的分析可以看到第 0 代堆大小的初始峰值要小得多,并且在请求完成时返回到基本为零(下图)。

Gen 0 After

对此进行更多搜索使我发现another更相关的SO问题,但是他的发现是这种内存使用不是问题,而在我的情况下,该服务实际上需要每天至少手动重新启动一次。

我还发现本文关于这个问题有以下说法(这似乎几乎完美地描述了正在发生的事情:

第 0 代可能在 64 位系统上拥有大量对象,尤其是当您使用服务器垃圾收集而不是工作站垃圾收集时。这是因为在这些环境中触发第 0 代垃圾收集的阈值较高,并且第 0 代垃圾收集可能会变得更大。当应用程序在触发垃圾收集之前分配更多内存时,性能会得到提高。

尽管问题仍然存在,但在服务器模式下,第 0 代堆似乎从未被收集过,而不是经常被收集。


经过大量研究、阅读和分析,我已经能够证明我们的 IIS 内存使用实际上在标准范围内;这是通过使用 SysInternals Test Limit 实用程序将服务器的物理内存使用量推至接近最大值来完成的,一旦完成此操作,我们所有的应用程序都会释放其内存。

我们的测试环境中确实仍然存在某种内存问题,我需要调查,但此时我想我可以自信地说这是完全不相关的。

这个故事的寓意是不要假设问题报告的原因是正确的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

服务器模式 GC 似乎从不收集 Gen 0 堆 的相关文章

随机推荐