每小时清空交换空间的cron脚本是否是一个不好的主意?

多年来,我一直遇到同样的问题:我的小型Ubuntu配置中使用的交换空间会随着时间的推移增加。我有这样的印象,主要是因为分配的内存即使有足够的空间,也不会返回到RAM中,除非用户执行了禁用交换的操作。
我制作了一个简短的cron命令来自动化这个过程,并且取得了良好的效果:
#! /bin/sh

echo "* */1 * * * root swapoff -a && swapon -a" >> /etc/crontab

但是因为这更像是一个把戏而不是真正解决问题的方法,我想知道它可能是个坏主意的潜在原因,或者如何改进这个脚本使其更巧妙一些?

29请原谅我的无知,但是你所说的“空间交换随时间增长”和“内存分配的空间清空到RAM中”具体是什么意思呢?通常情况下,你将一些空间分配给系统作为交换空间,然后就再也不会关心它了。谁会在乎交换空间实际上占用了多少呢?有什么问题吗? - dessert
1这是一个更好版本的例子:https://askubuntu.com/a/90399/15811 - Rinzwind
5你为什么要做这个?你为什么认为一些交换使用是不好的?我们在谈论多少交换使用量? - marcelm
我稍微修改了第一段,我的英语表达不太清楚... - Yvan Sraka
你正在问一个是非题,所以如果答案反映出这一点,请不要感到惊讶。 - user535733
25我有点困惑。你一直在谈论一个“问题”,但实际上并没有描述任何负面影响。为什么你认为这是一个问题? - David Schwartz
17如果某个东西进入交换空间并停留在那里,那是因为没有什么在使用它。而且如果没有什么在使用它,最好让RAM用于一些被访问的东西,例如缓存,而不是将数据重新交换回来。 - hobbs
12这样做有什么优势,比起完全关闭交换空间来说? - user253751
6个回答

像这样使用:是的,不好。在关闭交换空间之前,您确实需要检查是否有足够的可用内存。请参考https://askubuntu.com/a/90399/15811以获取更好的版本。

另外:您确定吗?分配交换空间并不意味着正在使用交换空间。命令vmstat,列si(交换入)和so(交换出)。如果它们保持为0,则表示您有其他问题。根据我的经验,交换空间很少被使用,您可能没有使用它,认为它不会清空,但实际上没有东西需要清空。


3等等,什么?如果内存不足以成功执行swapoff操作,swapoff会首先被OOM killer杀掉。是的,他们实际上硬编码了这个(通过系统调用进行检查)。 - Joshua
@Joshua 当然可以,但他希望它能自动运行,不出现错误。 - Rinzwind
5不去写自己的答案,详细解释一下,随着时间推移,交换使用量的增加一点也不是坏事。这意味着内核正在逐渐发现那些占用内存但从未被使用的垃圾,并将其移到交换空间中,以便内存可以用于实际对你有帮助的事情(比如能够缓存更多的文件系统数据,这样就不必再丢弃它并从磁盘重新读取)。 - R.. GitHub STOP HELPING ICE
@Rinzwind的cron在出现错误的作业方面工作正常,而且链接的脚本也没有使用vmstat - jpaugh

我会说这是个糟糕的主意。如果你认为你有空闲内存,并且一个活动的进程没有被从交换空间移到内存中,那么要么你的空闲内存并不像你想的那么多,要么该进程并不像你认为的那样活跃。

如果一个活跃的进程继续被交换,你应该修复导致内存压力的问题。如果它不是一个活跃的进程,那有什么大不了的呢?


1+1:这有什么大不了的?勿改正常运行的系统,我认为没有必要去干扰系统的核心功能,尤其是没有任何必要的情况下。 - dessert
3有时候我会遇到一个问题,即杀死一个有内存泄漏的进程(导致其他所有东西都被强行置换到交换空间),这样就只剩下大约10%的内存被使用了...但是所有正在运行的程序都在交换空间中,直到我再次访问它们。所以每次你触碰某个程序,都会有两秒的延迟。我理解原po的想法,自动完成这个过程确实会很方便,但这并不是正确的方法。 - SomeoneSomewhereSupportsMonica
1@某个地方的人 但事实并非如此。如果进程泄漏内存,根据定义,它不会主动使用该内存(不读写它);它只是意外分配了内存。如果周围有其他活动进程,泄漏的内存将被交换出去,你的交换空间将充满垃圾,而不是你的物理内存。 - David Richerby
@DavidRicherby 如果你在后台打开了一个程序,那么这个程序仍然比内存泄漏不活跃 - 当你切换回该程序时,它必须从交换空间中恢复。 - SomeoneSomewhereSupportsMonica
@SomeoneSomewhere 你似乎误解了内存系统的工作原理。你不需要将整个进程放在物理内存中:交换空间是以单个页面为粒度进行管理的。任何长时间未使用的页面都有可能被交换出去,而完全由泄漏内存组成的页面将永远不会再被使用,因此在被交换出去后也不会再被交换回来。 - David Richerby
@DavidRicherby 我不确定这是否严格意义上的“泄漏”,它可能仍在为某种原因循环使用分配的内存。但是我有一个应用程序,在特定情况下会使用完所有可用的RAM。一旦发生这种情况,切换到几乎任何其他程序都会导致硬错误,并且即使关闭了有问题的程序,这种情况仍会持续,直到清空交换空间。 - SomeoneSomewhereSupportsMonica
关键是,如果有1个16GB的内存被使用,并且页面文件中有5GB(包括用户空间程序),我更希望看到操作系统主动将页面文件加载回RAM中。 - SomeoneSomewhereSupportsMonica

这是个糟糕的主意。

内核在物理内存接近满时就开始将数据复制(而不是移动)到交换空间,因为如果某个进程需要大量内存,任何已经在交换空间中有有效副本的页面都可以立即重用,而无需再次写入磁盘。

通常情况下,这主要发生在长时间未访问的页面上,这表明它们很可能不会很快被访问。

如果你明确地丢弃这些副本,那没有任何好处,因为数据仍然存在于内存中,但当某个进程想要分配大量内存并且需要进行交换时,这可能会降低速度。

当物理内存使用超过50%时,内核也会始终使用交换空间,所以即使你安装了足够的内存,这些数字也不会为零。


4我认为你假设/proc/sys/vm/swappiness的值保持默认值70,这对服务器来说是好的,可以比较积极地清除一段时间内未访问过的脏页面,以便为更多的页面缓存腾出空间。但这通常对桌面电脑来说并不好,因为 alt-tab 切换会变慢。 - Peter Cordes
@PeterCordes,如果页面实际上被驱逐了,那么缓存中的访问次数肯定比相关应用程序页面多,因此使用这些作为磁盘缓存是有益的。我可以理解Alt-Tab性能对用户来说比如大型项目的编译时间更加显著,但很难制定一个既能保证即时响应又不牺牲太多性能的策略。 - Simon Richter
1换句话说,内核被调整为优先考虑吞吐量(swappiness=70),但对于桌面用户体验来说,延迟更重要。这是一个权衡。如果你经常编译的东西稍微大了一点,无法完全放入页面缓存中,那么可以将swappiness略微调高,比如20或30,而不是5或10。另请参考http://www.akitaonrails.com/2017/01/17/optimizing-linux-for-slow-computers。将`vm.vfs_cache_pressure`设置低于100也有利于缓存inode /目录元数据而非数据页,这对于界面的响应性也很好。 - Peter Cordes
1其他可调整的参数:写回阈值。这些参数控制在有文件写操作后,Linux开始向磁盘写入数据的速度以及允许存在多少个脏页(即可以用于写缓存的内存容量)。详见链接:https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/。 - Peter Cordes

这是一个不好的想法。如果有用的话,Linux内核会以这种方式实现它。我认为没有理由改变超过几个调整参数,因为这样一个简单的shell脚本很可能不比内核开发人员的算法更聪明。
基本上你有两种情况:
1.在交换空间中的进程根本没有使用。你为什么要把它们拉回到RAM中呢?
2. RAM很少,所以它们被交换出来,你将它们拉回到RAM中。然后你的系统会尽快再次把它们放回交换区。
所以有两个主要的观点:
1.首先,当RAM太少无法同时运行所有程序时,你的系统将变得很慢。交换将帮助你运行更多的程序,但不能快速切换到很少使用的程序,这些程序可能被交换出去。没有交换可能会导致很少使用的程序被杀死或发送当前正在使用的程序一个内存异常。
2.其次,交换是一件好事,而且在交换中有东西也是一件好事,因为你有免费的RAM可以用于当前不使用的程序。
尽管不会因为太多程序而出现内存不足的问题,但某些程序可能会根据当前可用的RAM分配内存(也许您的浏览器会使用更多的memcache,从而使您能够更快地浏览网页),而内核可以将空闲的RAM用于磁盘缓存和类似的优化。当您强制清空交换空间时,内核将丢弃其读取缓存,例如启动新的Firefox实例将比仍在磁盘缓存中的Firefox花费更长的时间。
如果您想调整内核的行为,请参阅swappiness参数
@peter-cordes提供了两个额外的资源:
- 优化慢速计算机的Linux - https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/ 如果你真的想要一个空的交换空间,你可以永久关闭交换空间。我不明白为什么开启它一个小时然后清空它会比不开启交换空间更有优势。

1参见以下链接以获取更多的调优建议和详细信息:http://www.akitaonrails.com/2017/01/17/optimizing-linux-for-slow-computers 和 https://lonesysadmin.net/2013/12/22/better-linux-disk-caching-performance-vm-dirty_ratio/。 - Peter Cordes

您可以通过告诉内核释放缓存来实现相同的结果:
echo 3 > /proc/sys/vm/drop_caches

这样你就可以避免可能的内存不足瞬间,并让内核决定什么是必要的,什么可以被丢弃。

与常见的想法相反,SWAP本身并不是坏事。
实际上,减慢系统速度的是内核活动,将数据从RAM移动到SWAP再移到RAM,即“swappiness”参数。
系统会自动根据“swappiness”配置进行操作,将非活跃进程的内存转储到硬盘交换分区中。
我曾经使用一台RAM内存较少的机器工作了多年,总是有一些SWAP内存被使用。直到你试图关闭打开的应用程序,将内存移回RAM时,我的机器才开始变得繁重。
  • 因此,通过不断清理SWAP内存,可以极大地增加机器的工作负荷。
  • 在SWAP分区上运行内存的应用程序可能会导致其执行出错。
我建议你仔细研究一下哪些应用程序在命令行中使用了你的内存,可以使用htop应用程序,并决定关闭一些应用程序。gnome-system-monitor也可以在其进程选项卡中提供有用的信息。 如果有一些占用大量内存的大型应用程序,请不要同时运行它们。