在很多情况下,我都看到 Linux 系统上存在这样一种行为:大量的文件系统写入操作(例如,几 GB 的写入,速度非常快)将使内存不堪重负,显然是在等待 I/O 操作完成并将缓冲数据(已写入)刷新到磁盘以释放内存以供后续写入。当这种情况发生时,如果我查看“vmstat -s”,我可以看到可用内存量越来越少,直到达到零。我最常在写入速度非常慢的磁盘(例如带有文件系统的 USB 连接的外部驱动器)时看到此问题,但我也在更多“常规”SATA 磁盘上看到过这种情况,当时大量数据被非常快速地写入。在最好的情况下,这似乎会导致写入操作最终阻塞,等待内存可用。在最坏的情况下,如果系统处于这种状态后继续发生大量写入,内存压力就会变得非常大,以至于 OOM Killer 会运行并随机终止进程以释放内存。显然,甚至不需要多个用户进行写入即可实现这一点,因为当我尝试非常快速地向文件系统写入大量数据时,我自己就创建了这种情况(甚至没有其他人使用该系统)。
我的猜测(我强调,这只是一个最佳猜测)是系统在将缓冲输出刷新到磁盘并释放相关内存方面并不是特别积极。但我不确定我可以调整什么,甚至查看什么,以确定这是否确实如此,也许可以让写入缓冲区的刷新更积极。
就猜测发生了什么而言,我是否走在正确的轨道上?如果是这样,我可以调整什么来尝试让系统更积极地将待处理的 I/O 刷新到磁盘并释放缓冲内存?
答案1
这听起来像是一个众所周知的话题(例如参见有害的 USB 记忆棒失速问题和减少烦人的后台写回在 LWN 上),但不幸的是,您没有告诉我们系统上的软件版本(例如内核版本),因此很难说出任何与您的情况太具体的事情。我从未发现过多的写回会导致 OOM(相反,它导致我的响应能力不佳)。要检查它是否真的全部与写回有关(而不是在 OOM 情况下可能很容易丢弃的缓存内存),您需要监视 Dirty 和 Writeback 行,/proc/meminfo
并仔细查看 OOM splat 中显示的内存状态。
一般来说,在较新的内核(撰写本文时)上,这应该不是什么大问题,因为在 4.10 中引入了执行动态写回限制的措施(但请注意如果你在 4.12+ 版本上使用 CFQ I/O 调度程序,则默认禁用写回限制)。
在手动方面,Chris Siebenmann 发现调整dirty_background_bytes
并dirty_bytes
保持他的机器在写入 USB 驱动器时响应。这些价值观存在于/proc/sys/vm
之前链接的 LWN USB 棒摊位文章中,并与其他价值观一起提及(另请参阅限制 Linux 后台刷新(脏页)有关此技术的讨论)。但请注意:错误地设置这些值可能会影响吞吐量。