逐渐增长的交换使用量是否是内存泄漏的指标?

逐渐增长的交换使用量是否是内存泄漏的指标?

我想了解我的服务器 (Windows Server 2012R2) 上是否存在内存泄漏。该服务器有 48 GB RAM,设计为仅运行 DBMS (SQL Server 2014),但还安装了其他工具,如 Symantec Endpoint Protection、FireEye 和一些监控工具/服务。它当前配置为保留 42 GB 给 DBMS,剩下 6 GB 给 OS 和其他服务。当只为 OS 和其他服务保留 4 GB 时,会出现内存不足错误,在我将其增加到 6 GB 后,这种情况就消失了。对于 SQL Server 计算机来说,高 RAM 使用率本身是正常的,因为 SQL Server 会将数据缓冲在 RAM 中。

让我担心的是,交换使用量(性能计数器 Paging File->Usage)在过去 2 个月中逐渐增加,目前已达到 24 GB(交换文件大小)的 15%。我不确定这是否正常,因为 Windows 即使在正常情况下也会将内容放入交换中,或者这是否表明 6 GB 一段时间后也不够用。下图中的绿线是 RAM 使用量(当我重新启动 SQL Server 时急剧下降并迅速恢复),黄色是自 5 月中旬以来的交换使用量。

交换使用图像

交换使用图像

我做了什么:

  1. 转储了性能计数器“进程->专用字节”。这里没有什么可疑之处。按 MB 计算的 TOP10 是(总共 44711 MB):

    • sql服务器 41322
    • 504 已选中
    • 316 号
    • splunkd 285
    • ccsvchst#1 260
    • 监控主机 233
    • 151 号
    • 监控主机#1 129
    • 健康服务 116
    • svchost#4 110
  2. 尝试重新启动单个服务(SQL Server、xagt/Fireeye、splunkd)。这对交换使用没有影响。

  3. 尝试使用 Sysinternals 的 RAMMap 和 VMMap 工具获取更多信息,因为我怀疑某些进程通过内存映射文件泄漏内存,而这些内存不计入私有字节。

    RAMMap 报告如下(遗憾的是,文件摘要/文件详细信息下的文件使用量加起来不到 300 MB,尽管报告的映射文件活动大小为 2659 MB):

    来自 rammap 的截图

    来自 rammap 的截图

我有另一台安装了相同工具的服务器,但有 96 GB RAM 和 16 GB 交换空间。RAM 使用率低于 50%,但交换使用率也(几乎)持续增加,目前为 28%。

在另一台服务器上交换使用情况

在另一台服务器上交换使用情况

这种行为正常吗?如果不正常,我该如何找到有问题的进程?

答案1

备用交换存储是一个可参考的参数。当它足够时,就不需要过度使用内存。我之前的回答并不是真正的解释。

结论是,发帖者确实存在内存泄漏,但工具中没有显示出来。这通常意味着泄漏发生在 Windows 或某些第三方驱动程序中。

此类泄漏很难发现,而且即使发现,也通常是无法修改的专有代码。

由于本例中的泄漏很小,且不会影响性能,因此该问题主要只是令人烦恼。 可以通过不时重启来修复。 对于发帖者来说,重启的频率甚至可以低至每月一次。


当可用信息较少时,先前的答案是:

您显然认为,只有当 Windows(或任何操作系统)的 RAM 不足时才会使用交换空间。事实并非如此。

当 RAM 耗尽时,操作系统必须准备好换出进程。因此,对于任何请求 RAM 的进程,操作系统都会分配与请求量相等的备用交换空间,甚至在批准 RAM 请求之前就分配了该空间。分配的交换空间不一定是作为特定磁盘扇区分配的,但操作系统会确保在需要时有足够的可用空间。

您观察到的增加意味着您的 DBMS 正在缓慢增加其内存大小并请求更多 RAM。交换相应增加。

为了完全安全,交换空间应等于 RAM 大小。您分配的 6 GB 远远不够。交换使用量的增加不应令人担忧。

答案2

我认为这是因为:

当某些内容被调出页面并稍后读回时,内核不会将其从页面文件中删除,直到文件已满或 RAM 中的页面发生更改。这样,如果它需要再次调出该块,它可以这样做而不必实际将页面写入磁盘:内容已经在那里了

这个答案

另外从那里的评论来看,Microsoft 建议您的交换足够大,以至于在任何给定时间只有 50-75% 的使用率......这在这里不是问题。

微软还建议(来自同一链接):

内存,页面输出/秒:此计数器显示每秒有多少虚拟内存页面被写入页面文件以释放 RAM 页面帧用于其他用途。

如果您怀疑分页是性能瓶颈,那么这是最好的计数器。即使已提交字节数大于已安装的 RAM,如果页面输出/秒大多数时间很低或为零,则 RAM 不足不会造成重大性能问题。

简而言之:现代操作系统就像囤积者。它们只有在被迫的情况下才会放弃一些东西(达到某个限制并清除旧东西,或者某些东西发生变化,所以它放弃了过时的副本),基本上是因为它能够并且将来也许有用...

答案3

这可能是一件好事,表明服务器操作系统运行正常,使用交换空间释放 RAM 用于磁盘缓存。操作系统首次启动时,会运行一堆进程,但可能永远不会(或很少)做任何有用的事情,因为您没有使用 Windows 的这些部分。它们的内存可能会被调出,但这只会在操作系统尝试回收页面时逐渐发生。

在内存压力较低的情况下,操作系统偶尔会随机选择一个页面并查看它是否正在使用,例如将其标记为无效(但将其留在内存中,以便可以快速将其重新连接到拥有它的进程的页表中),这是很正常的。如果它没有很快被引用,操作系统可能会将其分页到磁盘上。(并立即回收它,或将其留在 RAM 中,直到需要更多页面。)

在 Linux 中,此过程的积极性由 来设置vm.swappiness。我不知道 Windows 是否有类似的调整设置。


24 GB 交换文件的 15% 仅为 3.6 GB,远低于为 DBMS 之外的所有内容保留的 6GB 大小。

希望您的操作系统只是在遇到随机内存压力时才将从未修改过的脏页换出。此类页面可能常见于启动后没有实际执行任何操作的程序,因为没有任何内容连接到它们的服务。

最好的情况是这样的页面永远不会被读取,因此它可以留在 RAM 之外。然后您的交换空间就会发挥作用,留下更多的 RAM 用于磁盘缓存和其他有用的内容。

@user3067860 的回答提供了另一个非常有用的线索:即使页面被读回,Windows 也会将其留在交换空间中,因此可以再次免费将其从 RAM 中逐出,而无需 I/O。只有当页面被修改(或释放,我猜,例如通过重新启动拥有它的任何进程)时,它才会从交换中删除。

在大多数只是坐在那里等待有人与它们对话的进程中,它们可能在启动期间分配了一些内存并写入其中,但现在只是坐在事件循环中等待永远不会发生的事件。或者每隔几秒或每天醒来一次,也许会触及一些堆栈空间和一两个页面。

但是在启动期间弄脏的其余页面将永远不会再被写入,并且如果不需要 Windows 服务,大多数页面甚至不会被读取。

因此从长远来看,我们预计这些页面中的大多数(堆栈和私有.data/.bss页面,以及动态分配,“堆”)最终将被调出。任何已读取但未写入的数据最终仍将进入交换空间,但也会在 RAM 中保持热状态。

当然,除了 DBMS 之外,还有一些其他因素执行一些操作,例如 Windows 更新和日志记录,因此总内存占用量可能会超出启动后的情况。


这个答案是基于操作系统的总体设计方式而做出的猜测,对实际的 Windows 服务器调整没有任何经验。 那里可能是一个实际问题,但如果您不管它,您的交换使用量也很可能会稳定下来。 我会密切关注,但除非您的交换使用量超过 6 GB,否则我不会担心。如果达到 12 GiB,那么也许可以安排重新启动。

由于重新启动 DBMS 不会影响交换使用,因此这些页面似乎不是来自它的。这很有道理;它实际上在做实际工作,并且可能经常写入其大部分内存页面。而您对物理 RAM 的分区可能会使 Windows 不会尝试回收其页面。

相关内容