如何仅将交换空间用于紧急情况?


41

我有一台Debian(Buster)笔记本电脑,具有8 GB RAM和16GB交换空间。我正在执行一项很长时间的任务。这意味着我的笔记本电脑在过去的六天内一直处于开机状态。

在执行此操作时,我需要定期将笔记本电脑用作笔记本电脑。这应该不成问题;长期运行的任务是受I / O约束,可以处理USB硬盘上的内容,并且不会占用太多RAM(<200 MB)或CPU(<4%)。

问题是几个小时后我回到笔记本电脑时,它会非常缓慢,可能需要30分钟才能恢复正常。这非常糟糕,崩溃监视器将其各自的应用程序标记为已冻结(尤其是浏览器窗口),并且开始错误地崩溃。

在系统监视器上查看,已使用的2.5 GB内存中约有一半转移到了swap中。我已通过删除交换空间(swapoff /dev/sda8)确认了这是问题所在。如果我没有交换空间就可以使用它,即使在24小时之后,它也几乎可以立即恢复运行。通过交换,实际上仅剩下前六个小时的前五分钟就变成了一块砖。我已经确认即使我不在时内存使用量也不会超过3 GB

我曾尝试降低swappiness另见:维基百科)对值100,但问题仍然存在。似乎经过一天的不活动之后,内核认为不再需要整个GUI,并将其从RAM擦除(将其交换到磁盘)。长期运行的任务是读取庞大的文件树并读取每个文件。因此可能是内核被混淆了以为缓存会有所帮助。但是,仅扫描一次具有约10亿个文件名的2 TB USB HD,额外的GB RAM就不会对性能产生很大的帮助。这是一台便宜的笔记本电脑,硬盘驱动器呆滞。它根本无法足够快地将数据加载回RAM。

如何告诉Linux仅在紧急情况下使用交换空间?我不想没有交换就跑。如果发生意外情况,并且操作系统突然需要额外的GB,那么我不希望任务被杀死,而宁愿开始使用swap。但是目前,如果我启用交换功能,则仅在需要时才可以使用笔记本电脑。

“紧急情况”的确切定义可能是一个有争议的问题。但是要澄清一下我的意思:紧急情况是系统处于交换或终止进程的状态而没有其他选择的地方。


什么是紧急情况?- 您真的要问吗?...希望您永远不会在燃烧的建筑物中发现自己!

对于这个问题,我无法定义所有可能构成紧急情况的东西。但是例如,紧急情况可能是当内核被迫压入内存以至于它开始使用OOM Killer终止进程时。当内核认为使用交换可以提高性能时,就不会出现紧急情况。


最终编辑: 我已经接受了一个答案,该答案恰好满足了我在操作系统级别上的要求。未来的读者还应该注意提供应用程序级解决方案的答案。


11
定义“紧急”,并说一些与使用交换时的任何普通情况有何不同。
库萨兰达

4
我想知道您是否想以某种方式定义一种特殊的越界“紧急事件”,该类型将允许内核使用交换,但否则将不使用该交换。AFAIK调出内存的速度很慢,而且无论如何都只能在紧急情况下完成,而“ swappiness”是唯一可以用来调整此行为的方式(但我不是Linux用户)。
库萨兰达

2
不,那是不正确的。这不仅是在紧急情况下。至少我以为我的问题很清楚,我只使用了8GB中的3GB ...这几乎不是紧急情况,但是内核无论如何都在交换。我建议您阅读互换性和周围的话题。关于交换的各种原因,有很多讨论。可以肯定的是我所要求的并不在内核中存在的概念,但我的要求是理由合理地合理..
菲利普·库寿龄

4
我认识到建议始终是“永不交换就运行”。但是内存大小已经超出了硬盘驱动器(HDD而不是SSD)的读写速度,这意味着交换已不再是一个好主意。感觉有些人相信8GB RAM + 8GB交换将执行16GB RAM + 0交换。如果确实做到了,那么Linux内核就出了点问题。
菲利普·库灵

7
@Philip Couling:不,关键是16 GB RAM + 16 GB交换将胜过16 GB和0交换-尤其是当您的代码恰好需要17 GB内存时:-)
jamesqf

Answers:


11

如今进行如此大的互换通常是一个坏主意。到操作系统交换了仅几GB的内存进行交换时,您的系统已经爬行到死亡(就像您看到的那样)

最好与小型备份交换分区一起使用zram。许多年来,默认情况下,许多操作系统(例如ChromeOS,Android和各种Linux发行版)已启用zram,尤其是对于RAM较少的系统。它比在HDD上交换要快得多,在这种情况下,您可以清楚地感受到系统的响应能力。固态硬盘上的情况要少得多,但是根据此处基准测试结果,即使使用默认的lzo算法,它仍然看起来更快。您可以将lz4更改为更高的性能,而压缩率要少一点。根据官方基准,它的解码速度是lzo的近5倍

还有,zswap尽管我从未使用过。可能值得一试,比较哪种案例更适合您的用例

此后,另一个建议是降低那些受IO限制的进程的优先级,并可能使终端以更高的优先级运行,以便即使系统负载很高,也可以立即在其上运行命令

进一步阅读


就我所知,您是说我可以创建一个zram块设备,将其用作交换,而将优先级较低的交换用作HDD分区?
菲利普·库林

@PhilipCouling如果您使用的是HDD,那么可以,绝对应该使用zram或类似的解决方案。交换的优先级应低于zram,以便Linux尝试先用完zram,然后再考虑交换。如果您使用Ubuntu,则zram-config软件包已经为您完成了优先级设置
phuclv

3
我接受此答案,因为它似乎完全符合我的要求。如果我仍然以降低的优先级启用了16GB交换,那么内核将仅在zswap用尽时使用它。IE:“紧急情况”。注意在debian-buster上,只需安装zram-tools即可非常容易地进行设置。
菲利普·库林

25

一种解决方法是确保启用内存cgroup控制器(我认为默认情况下,即使是半新内核也是如此,否则,您需要将其添加cgroup_enable=memory到内核​​命令行中)。然后,您可以在具有内存限制的cgroup中运行I / O密集型任务,这也限制了它可以消耗的缓存量。

如果您使用的是systemd,则可以在单元或包含它的切片中设置+MemoryAccounting=yesMemoryHigh/ MemoryMaxMemoryLimit(取决于使用cgroup v1或v2的情况而定)。如果是切片,则可以用来systemd-run在切片中运行程序。

来自我的系统之一的完整示例,用于运行具有内存限制的Firefox。请注意,这使用cgroups v2并设置为我的用户,而不是root用户(v2相对于v1的优势之一是将其委派给非root用户是安全的,因此systemd可以做到)。

$ systemctl --user cat mozilla.slice 
# /home/anthony/.config/systemd/user/mozilla.slice
[Unit]
Description=Slice for Mozilla apps
Before=slices.target

[Slice]
MemoryAccounting=yes
MemoryHigh=5G
MemoryMax=6G

$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/firefox &
$ systemd-run --user --slice mozilla.slice --scope -- /usr/bin/thunderbird &

我发现让用户只能使用切片来工作。系统一仅通过将选项放在服务文件中(或systemctl set-property在服务上使用)即可工作。

这是一个示例服务(使用cgroup v1),请注意最后两行。这是系统(pid = 1)实例的一部分。

[Unit]
Description=mount S3QL filesystem
Requires=network-online.target
After=network-online.target

[Install]
WantedBy=multi-user.target

[Service]
Type=forking
User=s3ql-user
Group=s3ql-user
LimitNOFILE=20000
ExecStartPre=+/bin/sh -c 'printf "S3QL_CACHE_SIZE=%%i\n" $(stat -c "%%a*%%S*.90/1024" -f /srv/s3ql-cache/ | bc) > /run/local-s3ql-env'
ExecStartPre=/usr/bin/fsck.s3ql  --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo  --log none «REDACTED»
EnvironmentFile=-/run/local-s3ql-env
ExecStart=/usr/bin/mount.s3ql --keep-cache --cachedir /srv/s3ql-cache/fs1 --authfile /etc/s3ql-authinfo --cachesize ${S3QL_CACHE_SIZE} --threads 4
ExecStop=/usr/bin/umount.s3ql /mnt/S3QL/
TimeoutStopSec=2m
MemoryAccounting=yes
MemoryLimit=1G

文档在中systemd.resource-control(5)


1
您不能仅使用做一些可比较且可移植的操作ulimit吗?
老职业

1
@OldPro不是真的。首先,AFIAK对包括页面缓存在内的总内存使用量没有限制(在这里使用量变得越来越高)。其次,内存的ulimit是每个进程的,即使长时间运行的任务派生,cgroup也可以工作。
derobert

我认为在较新的系统上默认启用内存记帐的原因是由于systemd版本238的更改。
sourcejedi

1
@sourcejedi是相对较新的。首次引入内存控制器时,仅使其可用(甚至不使用)就具有足够大的性能成本,某些发行版至少在默认情况下禁用了它,而您必须传递该内核命令行参数来启用它。性能问题已修复,因此已更改,最近,systemd默认也将其激活。
derobert

14

似乎经过一天的不活动之后,内核认为不再需要整个GUI,并将其从RAM擦除(将其交换到磁盘)。

内核正在做“正确的事情”。为什么它会在RAM中保留未使用的1个内存,从而实际上浪费了它,而不是将其用作缓存或其他东西?

我认为Linux内核不是免费或无意地换出页面,因此,如果这样做,必须将其他内容存储在RAM中,从而提高长期运行的任务的性能,或至少达到此目标。

如果您知道何时需要提前重新使用笔记本电脑,则可以使用at命令(或crontab)安排交换清理(swapoff -a;swapon -a)。

由于清理掉交换可能是过大的,甚至由于某种原因(如果不是所有东西都适合RAM)甚至触发了OOM杀手,您可能只是“取消交换” 2与要恢复的正在运行的应用程序有关的所有东西。

一种方法是将调试器附加gdb到每个受影响的进程,然后触发核心转储生成:

# gdb -p <pid>
...
generate-core-dump /dev/null
...
quit

如您所写,长时间运行的应用程序不会在初次通过之后重用其读取的数据,因此在特定情况下,长期缓存无用。然后,像Will Crawford所建议的那样,通过使用直接I / O绕过缓存应该是一个不错的解决方法。

或者,您可能只是在OS认为换出GUI应用程序和环境是个好主意之前,通过回显1或伪文件3来定期刷新文件缓存/proc/sys/vm/drop_caches

请参阅如何清空Linux系统上的缓冲区和缓存?有关详细信息。

1 在某种意义上未使用:自从很长一段时间以来就不再积极使用,记忆仍然与其所有者相关。
2 放回存储在交换区域中的RAM页面。


2
感谢您对可能原因的思考。我添加了一些问题,因为它可能是相关的。我想知道是否有一种方法可以降低针对应用程序自身内存的缓存优先级。
菲利普·库林

5
“我认为Linux内核不是免费或无意中交换页面,因此,如果这样做,那一定是在RAM上存储其他内容,从而提高性能。” –我认为这个措词有点含糊。只要有机会(例如,磁盘I / O很少),内核肯定会写页面进行交换。但是,它不会将它们从RAM中删除。这样,您就可以兼得两全:如果您很快又需要这些页面,则它们已经在RAM中,因此无需执行任何操作。如果紧急情况(如OP把它)出现的时候,你只需要免费RAM的页面,因为
约尔格W¯¯米塔格

3
…他们已经在交换。这就是为什么您希望“仅在紧急情况下”使用交换的原因,因为在紧急情况下,系统已经处于压力之下,最后要做的就是向其中添加大量磁盘I / O。
Mittag

2
导致它换出内存的原因可能是运行时间长:它正在访问磁盘上的文件。内存中的那些文件将比GUI的内存被更近地使用。
jpmc26

3
@JörgWMittag您是否有证据表明Linux内核在I / O使用率较低的情况下“以防万一”抢先将页面写入交换区域,即不将其从RAM中释放出来?
jlliagre

10

您正在运行的流程是您自己创建的吗?

如果是这样,可能值得调整代码以使用O_DIRECT标记来打开文件,该标记引用手册页 -

尝试最大程度地减少往返于此文件的I / O的缓存影响。通常,这会降低性能,但是在特殊情况下(例如,应用程序自行缓存时)很有用。文件I / O是直接在用户空间缓冲区中进行的。O_DIRECT标志独自致力于同步传输数据,但不能保证O_SYNC标志可以传输数据和必要的元数据。为了保证同步I / O,除O_DIRECT外还必须使用O_SYNC。有关更多讨论,请参见下面的注释。


1
另一个类似的方法(但可能更容易,因为我很确定O_DIRECT有对齐限制,并且如果读取的数据不大,则会降低性能),建议告诉内核您不再需要该数据,从内核中清除该数据。页面缓存。(通过电话或会提供链接,很抱歉)
derobert

1
@derobert例如,该nocache命令是执行此操作的便捷工具。(它使用LD_PRELOAD劫持了一些libc调用)。
sourcejedi

6

这是一个想法,我还没有尝试过(很抱歉,我现在没有时间尝试这个想法)。

假设您为后台进程创建了一个只有512MB内存的小型VM,我不确定是否要在主机系统上进行任何交换,调用以及关闭交换。


3

删除交换或将其减少约20%(可能因系统而异),因为最近的操作系统不再像几年前那样使用交换。它可能会回答您的一些问题:

->官方redhat.com

下面的一些Red Hat信息,

过去,一些应用程序供应商建议交换大小等于RAM甚至两倍于RAM的内存。现在,让我们想象一下上面提到的具有2GB RAM和2GB交换空间的系统。系统上的数据库被错误地配置为具有5GB RAM的系统。物理内存用完后,交换将被使用。由于交换磁盘比RAM慢得多,因此性能下降并发生颠簸。此时,甚至无法登录系统。随着越来越多的内存被写入,最终物理内存和交换内存都将完全耗尽,并且OOM杀手er进来,杀死一个或多个进程。在我们的情况下,有很多交换可用,因此性能不佳的时间很长。

https://wiki.debian.org/交换

以上Debian链接的一部分,

与要使用的掉期金额有关的信息和注意事项:

“传统上建议的交换空间数量是系统内存的两倍。随着时间的推移,交换空间已变为系统内存的一半和一半,这两个答案都是不错的基准,但随着时间的流逝,该问题的有用答案越来越少。有关您的系统和预期用途的变量很多,这些变量将确定您希望拥有的可用系统交换。”

您可以尝试:

“禁用Linux中交换的最佳方法”


个人说明:


因为我有6 GB RAM,并且在我最近所有的Linux操作系统中。我从未见过使用Swap的任何迹象。我确定必须关闭它以节省空间(再增加几GB),因为有时它会减慢我的系统的速度。


1
过去,一些应用程序供应商建议交换大小等于RAM甚至两倍于RAM的内存。我以某种方式感到更老了……尽管我仍然拥有一个〜528MB的硬盘和一个2.5GB的硬盘,但是以某种方式报价-好吧这是很久以前的事了...虽然有趣的报价和这也许可以解释为什么几年前我看到类似的问题。我相信我已经使用sysctl对其进行了修复,但是我不记得确切的设置是什么。
Pryftan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.