【问题标题】:WorkingSet Spike just before OutOfMemoryException就在 OutOfMemoryException 之前的 WorkingSet 峰值
【发布时间】:2012-12-01 17:29:36
【问题描述】:

我正在调查“传统”.NET 服务器应用程序在生产中引发 OutOfMemoryException 的事件。我的目的是解释通过性能监视器收集的数据的特定部分,并就如何继续前进寻求一些建议。让我从一个事实列表开始:

  1. 该进程已经运行了 20 多天,直到崩溃。
  2. 它崩溃了,因为抛出了 System.OutOfMemoryException 类型的异常。
  3. 过去也发生过类似的事件。同样,应用程序崩溃需要很长时间
  4. 进程已通过性能监视器由以下计数器监控:# Bytes in all Heaps、% Processor Time、Private Bytes、Working Set。
  5. 我们无法在生产环境中捕获任何内存转储,并且我们无法重现它。

在第一个屏幕截图中,您可以看到计数器在 7 天内的整体行为。事情相当稳定。第二个屏幕截图显示了崩溃前后最后一分钟的行为。 下午 3:13:49 记录了 OutOfMemoryException。

我的问题是: 1.Working Set 突然增加是什么意思?它总体稳定在 650 多 MB,并在 10 秒内攀升至 1.3GB。 2. 我应该专注于寻找在崩溃前触发OOM的东西,还是累积因素?如您所见,私有字节和所有堆上的字节非常稳定。

【问题讨论】:

  • 服务器应用程序基本上在做什么?我认为当时负载没有显着变化。
  • 它有许多本地连接到它的客户端,通过 .NET 远程处理。主要是处理输入请求,执行所需的操作来处理它们(包括大量的数据库查询)并回复。至于工作量,在它崩溃的那一刻是相当高的,但这在那个时候是很常见的。客户数量不是问题。这是一个可预测的数字 - 没有任何客户端连接溢出。
  • 很抱歉没有更多帮助。如果它稳定了 20 天,那么我将专注于最后 10 秒。在 10 秒内从 650mb 变为 1.3 意义重大。并不意味着找到重要的原因会很容易。任何工作的集合可能已经无限增长?
  • 欢迎任何意见!内存增加会影响工作集计数器,但不会影响 Private Bytes。这是我正在寻找的答案之一:WorkingSet 增加意味着什么?我过去处理过其他 OOM 情况,一直存在可见的内存泄漏(私有字节增加等)。
  • Private Bytes 通常会涵盖您的应用所触及的页面。工作集涵盖了最近读取和/或写入的所有资产私有字节、共享 dll、内存映射文件等。 PB 是平的,所以你的应用直接接触的页面似乎不是根本原因。 GC 堆大小是否与平坦的 PB 值相呼应?您可能正在加载一个新的 DLL、COM 或类似的东西?堆栈转储出 OOM 异常?接下来我会使用远程调试器或 Autocrash 转储 - blogs.msdn.com/b/dotnet/archive/2009/10/15/…

标签: .net memory out-of-memory perfmon working-set


【解决方案1】:

这类问题极难诊断。发生的事情很可能不是触发行为的单一条件的结果,而是一组同时发生的条件。

这是我们所知道的:

  1. 未显示累积性问题:如果问题是累积性的,我们预计会在事件发生前的 20 天内看到一些迹象。这并不意味着前面的操作可以忽略。触发行为的某些条件可能是预先安排的,并且更早开始。这是我们无法通过现有信息知道的事情。

  2. 堆稳定: Private Bytes 度量告诉我们保留了多少内存(未触及,如 stephbu 建议的那样)。 Bytes-in-all-Heaps 告诉我们当前根据内存管理器 (GC) 分配了多少保留内存。由于这两个都是稳定的,因此问题似乎不一定是内存泄漏。危险在于我们只有 10 秒的有趣数据,而且由于 GC 通常是相当被动的,因此不清楚这些统计数据的准确度(尤其是不稳定的工作集)。

  3. 工作集表明抖动:工作集告诉我们操作系统想要保持多少物理内存以确保合理的性能。不断增长的工作集表明抖动。不断增长的工作集通常与两件事相关:

    • 提高分配率

    • 增加对象寿命(通常是暂时的)

    没有显示增加的对象寿命,因为堆没有显示增长。增加分配率是可能的,但对象仍然是短暂的(因为未指示泄漏)。

这些观察向我表明,一些罕见事件(或一组事件)正在触发以下情况:

  • 高分配率

  • 中等大小的物体

  • 寿命不长

  • GC 正在崩溃

other reports 这些条件导致 OutOfMemoryExceptions。我不太确定它为什么会发生。如果您运行的是 32 位环境,那么一个可能的原因是地址空间的碎片。如果 GC 无法从操作系统获取连续页面,就会发生这种情况。

另一种可能性(我无法验证)是 GC 请求操作系统不要分页它正在处理的堆的部分。如果锁定页数变高,可能会导致内存不足。这个想法几乎完全是猜测,因为我对微软 GC 实现的内部了解不够。

我现在没有更好的解释,但如果有人可以提供,我肯定想要更好的解释。

最后,您可能想要验证是否启用了合理的Latency Mode。如果这是问题所在,我想我们会看到 Bytes-in-all-Heaps 的升级——所以可能没问题。

附言

你能检查一下第二张图表中虚线表示的变量是什么吗?如果是处理器使用,则与抖动一致。随着更频繁地调入内容的需求增加,磁盘 IO 应该增加,并且(在某个点)处理器使用百分比应该下降,因为一切都在等待磁盘。这只是一个额外的细节——如果处理器的使用没有过度下降,抖动仍然是一种可能性。这是因为部分软件可能仍然表现出良好的局部性并能够取得进展。

【讨论】:

  • 非常感谢您的详细意见。实际上,虚线是 CPU 使用率,在 OOM 前几个小时(从早班开始)确实很高。就在工作集开始增加时,CPU 使用率开始迅速下降。这是崩溃发生当天的图表:i.imgur.com/JYLlM.jpg
  • 也许最后 3 分钟的执行更清楚:i.imgur.com/w3kjT.jpg
  • @nantito 谢谢。这些额外的图表看起来与我的预期一致。 CPU 使用率的突然下降很可能是由于分页。
猜你喜欢
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 2012-12-08
  • 2017-02-22
  • 1970-01-01
  • 2019-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多