这类问题极难诊断。很可能发生的事情不是触发行为的单一条件的结果,而是一组同时发生的条件。
以下是我们所知道的:
没有显示累积性问题: 如果问题是累积性的,我们预计会看到导致事件发生的 20 天期间的一些迹象。这并不意味着前面的操作可以忽略。触发行为的某些条件可能是预先安排的,并且更早开始。这是我们无法通过现有信息知道的事情。
堆是稳定 的:Private Bytes 度量告诉我们保留了多少内存(未触及,如 stephbu 建议的那样)。Bytes-in-all-Heaps 告诉我们当前根据内存管理器 (GC) 分配了多少保留内存。由于这两个都是稳定的,因此问题似乎不一定是内存泄漏。危险在于我们只有 10 秒的有趣数据,而且由于 GC 通常是相当被动的,因此不清楚这些统计数据的准确度(尤其是不稳定的工作集)。
工作集表明颠簸: 工作集告诉我们操作系统想要保持多少物理内存以确保合理的性能。不断增长的工作集表明抖动。不断增长的工作集通常与两件事相关联:
没有指出增加的对象寿命,因为堆没有显示增长。增加分配率是可能的,但对象仍然是短暂的(因为未指示泄漏)。
这些观察结果向我表明,一些罕见的事件(或一组事件)正在触发以下情况:
高分配率
中等大小的物体
寿命不长
GC因此而颠簸
还有其他关于这些情况导致 OutOfMemoryExceptions 的报告。我不太确定它为什么会发生。如果您运行的是 32 位环境,那么一个可能的原因是地址空间的碎片。如果 GC 无法从操作系统获取连续页面,则可能会发生这种情况。
另一种可能性(我无法验证)是 GC 请求操作系统不要分页它正在处理的堆的部分。如果锁定页数变高,可能会导致内存不足。这个想法几乎完全是猜测,因为我对微软 GC 实现的内部了解不够。
我现在没有更好的解释,但如果有人能提供一个更好的解释,我肯定会想要一个更好的解释。
最后,您可能想要验证是否启用了合理的延迟模式。如果这是问题所在,我想我们会看到 Bytes-in-all-Heaps 的升级——所以它可能没问题。
附言
你能检查第二张图表中虚线表示的变量是什么吗?如果是处理器使用,则与抖动一致。随着更频繁地调入内容的需求增加,磁盘 IO 应该增加,并且(在某个点)处理器使用百分比应该下降,因为一切都在等待磁盘。这只是一个额外的细节——如果处理器的使用没有过度下降,抖动仍然是一种可能性。这是因为部分软件可能仍然表现出良好的局部性并能够取得进展。