Phi*_*ing 47 linux memory swap
我有一台带有8 GB RAM 和 16 GB 交换的 Debian (Buster) 笔记本电脑。我正在运行一个很长的运行任务。这意味着我的笔记本电脑在过去六天里一直处于运转状态。
这样做时,我需要定期将笔记本电脑用作笔记本电脑。这应该不是问题;长时间运行的任务受 I/O 限制,处理 USB 硬盘上的内容,并且不占用太多 RAM (<200 MB) 或 CPU (<4%)。
问题是当我在几个小时后回到我的笔记本电脑时,它会非常缓慢,可能需要 30 分钟才能恢复正常。这太糟糕了,以至于崩溃监视器将它们各自的应用程序标记为已冻结(尤其是浏览器窗口),并且事情开始错误地崩溃。
查看系统监视器,大约一半使用的 2.5 GB 被转移到交换中。我已经通过删除交换空间 ( swapoff /dev/sda8
) 来确认这是问题所在。如果我在没有交换空间的情况下离开它,即使在 24 小时后它也几乎立即恢复生机。使用交换,前五分钟实际上是一块砖,只剩下六个小时。我已经确认即使我不在时内存使用量也不会超过3 GB。
我尝试将swappiness(另见:维基百科)减少到10
和的值0
,但问题仍然存在。似乎在一天不活动后,内核认为不再需要整个 GUI 并将其从 RAM 中擦除(将其交换到磁盘)。长时间运行的任务是读取庞大的文件树并读取每个文件。因此,内核可能会误以为缓存会有所帮助。但是在一次扫描具有约 10 亿个文件名的 2 TB USB 硬盘时,额外的 GB RAM 不会对性能有太大帮助。这是一款价格低廉的笔记本电脑,硬盘速度很慢。它根本无法足够快地将数据加载回 RAM。
如何告诉 Linux 仅在紧急情况下使用交换空间?我不想在没有交换的情况下运行。如果发生意外情况,并且操作系统突然需要额外的几 GB,那么我不希望任务被杀死,而是希望开始使用交换。但目前,如果我启用交换,我的笔记本电脑就无法在需要时使用。
“紧急情况”的确切定义可能是一个有争议的问题。但要澄清我的意思:紧急情况是系统除了交换或终止进程之外别无选择。
什么是紧急情况?-你真的要问吗?...我希望你永远不会发现自己在燃烧的建筑物中!
我不可能在这个问题中定义可能构成紧急情况的所有内容。但是,例如,紧急情况可能是当内核被如此推入内存以至于它开始使用OOM Killer杀死进程时。当内核认为它可以通过使用交换来提高性能时,不是紧急情况。
最终编辑: 我已经接受了一个答案,该答案正是我在操作系统级别所要求的。未来的读者还应该注意提供应用程序级解决方案的答案。
der*_*ert 28
一种解决方法是确保启用内存 cgroup 控制器(我认为即使在最近的内核中也是默认设置,否则您需要添加cgroup_enable=memory
到内核命令行)。然后,您可以在具有内存限制的 cgroup 中运行 I/O 密集型任务,这也限制了它可以消耗的缓存量。
如果您使用 systemd,您可以在单元或包含它的切片中设置+MemoryAccounting=yes
和MemoryHigh
/MemoryMax
或MemoryLimit
(取决于您使用的是 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 &
Run Code Online (Sandbox Code Playgroud)
我发现要让用户工作,我必须使用切片。系统一只需将选项放入服务文件(或systemctl set-property
在服务上使用)即可工作。
这是一个示例服务(使用 cgroup v1),注意最后两行。这是系统 (pid=1) 实例的一部分。
$ 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 &
Run Code Online (Sandbox Code Playgroud)
文档在systemd.resource-control(5)
.
jll*_*gre 14
似乎在一天不活动后,内核认为不再需要整个 GUI 并将其从 RAM 中擦除(将其交换到磁盘)。
内核正在做正确的事情™相信它。为什么它会在 RAM 中保留未使用的1 个内存并因此基本上浪费它而不是将其用作缓存或其他东西?
我不认为 Linux 内核是无偿的或预期的换出页面,所以如果这样做,必须在 RAM 上存储其他东西,从而提高长期运行任务的性能,或者至少达到这个目标。
如果您知道何时需要提前重新使用您的笔记本电脑,您可以使用at
命令 (或crontab
) 来安排交换清理 ( swapoff -a;swapon -a
)。
由于清理交换可能是矫枉过正,甚至会触发 OOM 杀手,如果出于某种原因,并非所有内容都适合 RAM,您可能只是“取消交换” 2与您想要恢复的正在运行的应用程序相关的所有内容。
一种方法是将调试器附加gdb
到每个受影响的进程并触发核心转储生成:
# gdb -p <pid>
...
generate-core-dump /dev/null
...
quit
Run Code Online (Sandbox Code Playgroud)
正如您所写,您的长时间运行的应用程序不会重用它在初始传递后读取的数据,因此您处于长期缓存无用的特定情况下。然后像 Will Crawford 建议的那样使用直接 I/O 绕过缓存应该是一个很好的解决方法。
或者,你可能只是定期呼应刷新文件缓存1
或3
到/proc/sys/vm/drop_caches
伪文件中OS认为这是一个好主意,换出你的GUI应用程序和环境之前。
请参阅如何清空 Linux 系统上的缓冲区和缓存?详情。
1从某种意义上说未使用:在很长一段时间内不再积极使用,内存仍然与其拥有者相关。
2放回存储在交换区的 RAM 页。
phu*_*clv 13
如今进行如此大的掉期通常是一个坏主意。当操作系统只交换几 GB 的内存进行交换时,您的系统已经爬行至死(就像您看到的那样)
最好与小的备份交换分区一起使用zram
。许多操作系统,如ChromeOS、Android 和各种 Linux 发行版(Lubuntu、Fedora)已经默认启用 zram 多年,特别是对于 RAM 较少的系统。它比在 HDD 上交换要快得多,在这种情况下,您可以清楚地感受到系统响应能力。在 SSD 上不那么重要,但根据这里的基准测试结果,即使使用默认的 lzo 算法,它似乎仍然更快。您可以更改为lz4以获得更好的性能,同时压缩率更低。根据官方基准,它的解码速度比 lzo 快近 5 倍
事实上Windows 10和macOS默认也使用类似的页面文件压缩技术
还有zswap
虽然我从来没有用过它。可能值得一试并比较哪个更适合您的用例
之后的另一个建议是降低那些 IO 绑定进程的优先级,并可能让终端以更高的优先级运行,这样即使系统负载很高,您也可以立即在其上运行命令
这是一个我自己没有尝试过的想法(很抱歉我现在没有时间对此进行试验)。
假设您为后台进程创建了一个只有 512MB 内存的小型 VM,我不确定您是否希望它具有任何交换、调用和关闭主机系统上的交换。
归档时间: |
|
查看次数: |
5734 次 |
最近记录: |