如何驯服 Linux 响应能力、内存和分页

use*_*871 28 memory linux performance

关于溢出的第一个问题 =)... +100 赏金。直到现在想不出我真正关心的事情:

我真的厌倦了 Linux 桌面响应的状态,例如http://brainstorm.ubuntu.com/item/85/——在可用内存低的情况下,或磁盘吞吐量高的情况下,系统会变慢一个爬行; 这对于需要良好性能的应用程序来说绝对是糟糕的。此外,用户界面完全没有响应。将其与 OS X 进行比较,如果应用程序占用资源,则始终可以选择单击强制退出它,而在 Linux 中,我什至无法使用 alt-tab 或切换桌面,甚至无法使用 ctrl-alt-f1 来获取终端——我可以,每次操作只需要大约 1-2 分钟。

我使用 gkrellm 以便我可以看到情况的发展。通常内存利用率会变得非常高,或者磁盘吞吐量急剧增加。

它的硬件还不错,具有 2.6GHz 四核和 4GB 800MHz DDR2 RAM(本来应该有 6GB,但由于硬件不兼容,无法与旧设置混合搭配)。当我不可避免地获得更多内存时,这个问题可能会消失,但我不认为这是问题的核心。我什至在不同的磁盘上有两个交换分区。

我觉得问题有三个:

  • 占用大量内存的失控程序——必须为这些程序制定法律,限制它们
    • (例如 Chrome 上的标签,每个标签是 20-50MB,其中一些可以使用数百 MB)
    • (例如,我不得不禁用并从 cron 中删除的其他程序,如 update-db 和索引器,因为它们在运行时会降低系统速度,等等)
  • 内核或某种总线争用中发生了一些可怕的事情,例如高磁盘吞吐量的情况使整个系统变慢(可能是通过分页重要程序)
  • 内核没有优先考虑 UI 或重要程序的资源,例如内存、分页,甚至处理器利用率

点赞转到:

因此,我正在寻找一种解决方案,使所有此类程序都消失。特别是,我正在寻找一种解决方案,使进程按比例减慢,而系统和其他程序仍然完全不受影响并且响应时间足够长以手动杀死某些东西。此外,窗口管理器进程(以及可能影响 UI 响应的任何其他进程)在所有情况下都应该响应。

特别是我对/etc/security/limits.conf( man limits.conf)很感兴趣,但我担心这只会提供每个用户的控制权,并且文件中的注释示例在描述或从哪里开始方面似乎相当不透明。我希望它limits.conf有效,但如果它甚至不起作用,或者它不是我的问题的合适解决方案,或者像我试图实现的那样细粒度,我也不会感到惊讶。每个进程名称limits.conf将是理想的,假设再次假设limits.conf 工作。我很乐意尝试人们提供的limits.conf,以测试它是否有效,尽管此时我对所有解决方案持开放态度。

深入了解 OS X 如何保持如此良好的 UI 响应能力也可能很有用。

我已经将 my/tmp和 cache 文件夹调整为 on tmpfs,通常磁盘利用率接近于零。

隐约相关的话题:

  • 内存过载

我认为不会奏效的答案:

  • swapoff (这仍然可以让占用内存的程序逍遥法外,如果内存真的很差,系统将永久冻结 - 向任何可以建议在交换和针对特定程序之前调用 OOM-killer 的调整的人点赞)
  • echo ?? > /sys/.../swappiness (无明显效果)
  • nice (从未工作过)
  • ionice (从未注意到有什么不同)
  • selinux(程序不兼容好像是个噩梦)
  • 实时 linux,即可以中断内核(不想处理编译和更新自定义内核;如果它已迁移到存储库可能没问题)
  • *

Tur*_*o J 6

听起来你的系统进入了大量交换。使用vmstat 1可能会揭示一些细节 - 只需让它在终端窗口中运行并在减速开始时切换到它。

我不会将 /tmp 和“缓存”放入 tmpfs 中,而是使用带有该noatime选项的普通磁盘文件系统。经常使用的数据无论如何都会保留在缓存中,并且可以将旧数据写入磁盘以释放一些 RAM 用于应用程序。如果 /tmp 和/或缓存变大,这可能会有很大帮助。

  • 哎哟。从未见过需要如此大量交换的 Linux 系统。您是否使用 `df -m` 检查过 tmpfs 文件系统中使用了多少内存?** 是** 相对较快地吃掉您的 RAM。 (2认同)

小智 6

我不是内核开发人员,但我花了数年时间对这个问题进行哲学思考,因为我多次遇到这个问题。我实际上想出了一个比喻来形容整个情况,所以让我告诉你。我会在我的故事中假设“交换”之类的东西不存在。无论如何,现在 32 GB RAM 的交换没有多大意义。

想象一下你的一个街区,水通过管道连接到每栋建筑,城镇需要管理容量。假设您每秒只能生产 100 个单位的水(并且所有未使用的容量都被浪费了,因为您没有储水箱)。每个家庭(家庭 = 一个小应用程序、终端、时钟小部件等)每秒需要 1 个单位的水。这一切都很好,因为你们的人口大约有 90 人,所以每个人都能得到足够的水。

现在市长(=你)决定你要开一家大餐厅(=浏览器)。这家餐厅将容纳多个厨师(=浏览器选项卡)。每个厨师每秒需要 1 个单位的水。您从 10 名厨师开始,因此整个社区的总用水量为 100 单位水,这仍然很好。

现在有趣的事情开始了:您聘请另一位厨师到您的餐厅,这使得总用水量达到 101,而这显然是您没有的。你需要做点什么。

水管理(=内核)有 3 个选项。

1.第一种选择是为最近没有用水的家庭断开服务。这很好,但如果断开连接的家庭想要再次使用水,他们将需要再次经历冗长的注册过程。管理层可以断开多个家庭的连接以释放更多的水资源。实际上,他们会断开所有最近没有用水的家庭的连接,从而始终保持一定量的免费水可用。

尽管您的城镇继续运转,但缺点是进展会停滞不前。您的大部分时间都花在等待水管理部门恢复您的服务上。

这就是内核对文件支持的页面所做的事情。如果您运行大型可执行文件(如 chrome),其文件将被复制到内存中。当内存不足或有最近没有访问过的部分时,内核会删除这些部分,因为它无论如何都可以从磁盘重新加载它们。如果这样做过度,这会使您的桌面陷入停顿,因为一切都将只是等待磁盘 IO。请注意,当您开始执行大量 IO 时,内核也会删除许多最近最少使用的页面。这就是为什么在复制了几个大文件(如 DVD 图像)后切换到后台应用程序需要很长时间的原因。

这对我来说是最烦人的行为,因为我讨厌打嗝而你无法控制它。能够关闭它会很好。我在想一些事情

sed -i 's/may_unmap = 1/may_unmap = (vm_swappiness >= 0)/' mm/vmscan.c
Run Code Online (Sandbox Code Playgroud)

然后你可以将 vm_swappiness 设置为 -1 来禁用它。这在我的小测试中效果很好,但可惜我不是内核开发人员,所以我没有将它发送给任何人(显然上面的小修改还没有完成)。

2.管理层可以拒绝新厨师要水的要求。这最初听起来是个好主意。然而,有两个缺点。首先,有些公司即使不使用它们也要求大量的水订阅。这样做的一个可能原因是避免在需要额外水时与水管理部门交谈的所有开销。他们的用水量取决于一天中的时间。例如,在餐厅的情况下,与午夜相比,公司在中午需要更多的水。因此,他们要求所有可能使用的水,但这会浪费午夜的水分配。问题在于,并非所有公司都能正确预测其使用高峰,因此他们要求更多,希望他们永远不需要担心要求更多。

这就是 Java 的虚拟机所做的:它在启动时分配一堆内存,然后从中工作。默认情况下,内核只会在您的 Java 应用程序实际开始使用它时分配内存。但是,如果您禁用过度使用,内核将认真对待预留。如果它确实有资源,它只会允许分配成功。

然而,这种方法还有另一个更严重的问题。假设一家公司开始每天请求一个单位的水(而不是 10 步)。最终你会达到一个状态,你有 0 个空闲单位。现在这家公司将无法分配更多。没关系,反正谁在乎大公司。但问题是小户型也不能多要水!您将无法建造小型公共浴室来应对突然涌入的游客。您将无法为附近森林的火灾提供应急用水。

在计算机方面:在没有过度使用的内存非常低的情况下,您将无法打开一个新的 xterm,您将无法 ssh 进入您的机器,您将无法打开一个新选项卡来搜索可能的修复。换句话说,当内存不足时,禁用过度使用也会使您的桌面无用。

3.当公司开始使用过多的水时,这里有一个有趣的方法来处理这个问题。水务管理把它炸了!字面意思是:它前往餐厅现场,将炸药扔进去,然后等到它爆炸。这将立即大大减少城镇的用水需求,因此新人可以搬进来,您可以创建公共浴室等。作为市长,您可以重建餐厅,希望这一次需要更少的水。例如,如果里面已经有太多人,您会告诉人们不要进入餐厅(例如,您将打开更少的浏览器标签)。

这实际上是内核在耗尽所有选项并且需要内存时所做的事情:它调用了 OOM 杀手。它选择一个大型应用程序(基于许多启发式)并杀死它,释放大量内存但保持响应式桌面。实际上,Android 内核更积极地执行此操作:当内存不足时,它会杀死最近最少使用的应用程序(与仅作为最后手段执行此操作的库存内核相比)。这在 Android 中被称为 Viking Killer。

我认为这是解决这个问题的最简单的方法之一:你并没有比这更多的选择,所以为什么不早点克服它,对吧?问题是内核有时会做很多工作来避免调用 OOM 杀手。这就是为什么你会看到你的桌面很慢而且内核没有做任何事情。但幸运的是,有一个选项可以自己调用 OOM 杀手!首先,确保启用了神奇的 sysrq 键(例如echo 1 | sudo tee /proc/sys/kernel/sysrq),然后每当您觉得内核内存不足时,只需按 Alt+SysRQ,Alt+f。

好的,所有这些都很好,但您想尝试一下吗?内存不足的情况很容易重现。我有一个非常简单的应用程序。您将需要运行它两次。第一次运行将确定您有多少可用 RAM,第二次运行将造成内存不足的情况。请注意,此方法假定您已禁用交换(例如执行 a sudo swapoff -a)。代码和用法如下:

// gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    int limit = 123456789;
    if (argc >= 2) {
        limit = atoi(argv[1]);
    }
    setbuf(stdout, NULL);
    for (int i = 1; i <= limit; i++) {
        memset(malloc(1 << 20), 1, 1 << 20);
        printf("\rAllocated %5d MiB.", i);
    }
    sleep(10000);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是你如何使用它:

$ gcc -std=c99 -Wall -Wextra -Werror -g -o eatmem eatmem.c
$ ./eatmem
Allocated 31118 MiB.Killed
$ ./eatmem 31110
Allocated 31110 MiB.Killed
Run Code Online (Sandbox Code Playgroud)

第一次调用检测到我们有 31,118 MiB 的空闲 RAM。所以我告诉应用程序分配 31,110 MiB RAM,这样内核就不会杀死它,而是吃掉我几乎所有的内存。我的系统死机了:连鼠标指针都没有移动。我按下了 Alt+SysRQ,Alt+f,它终止了我的eatmem 进程,系统恢复了。

尽管我们介绍了在低内存情况下的选择,但最好的方法(就像任何其他危险情况一样)是首先避免它。有很多方法可以做到这一点。我见过的一种常见方法是将行为不端的应用程序(如浏览器)放入与系统其余部分不同的容器中。在这种情况下,浏览器将无法影响您的桌面。但是预防本身超出了问题的范围,所以我不会写它。

TL;DR:虽然目前没有办法完全避免分页,但您可以通过禁用过度使用来缓解完全系统停机。但是您的系统在内存不足的情况下仍然无法使用,但方式不同。不管上述如何,在内存不足的情况下,按 Alt+SysRQ,Alt+f 可以杀死内核选择的一个大进程。您的系统应该会在几秒钟后恢复其响应能力。这假设您启用了魔法 sysrq 键(默认情况下不是)。


Law*_*ceC 4

将所有临时文件和缓存文件放在 a 上tmpfs会降低您拥有的可用 RAM 量,因此您可能会导致系统比没有此操作所需的时间更快地进行交换。

听起来您有一些应用程序依赖于某种正在过载的内核设施或驱动程序。除了您正在使用浏览器和索引器以及您已禁用索引器之外,您无需过多详细了解其他类型的应用程序。

您可以尝试切换到消耗较少资源的桌面环境或窗口管理器,例如 LXDE 或 IceWM。在工作中,我使用安装了 LXDE 和 ROX-Filer 的 Linux 系统来构建一个非常小的桌面环境。这个Linux系统的目的是运行VMWare Player,以便我可以同时运行Windows XP和Windows 7。它的硬件规格与您所说的类似,并且在我将硬件置于如此重的负载下,我没有太多的响应问题。我对 Linux 本身没有任何响应问题(通常是虚拟机有时让我等待一秒钟,并且在 2 个虚拟机 + 1 个操作系统之间共享 1 个磁盘,这是预期的),并且始终能够在任何时候暂停或关闭虚拟机我想要。这包括让 Firefox 在 Linux 上经常在后台运行。

所以对我来说,它指出了您正在运行的特定应用程序的一些问题。

您的磁盘驱动器是否启用了 DMA?(使用hdparm)如果您使用全磁盘加密,则需要所有磁盘流量都经过 CPU,这会抵消 DMA 的大部分优势。其结果是高磁盘流量会导致 CPU 峰值,从而降低整个系统的速度。(编辑:澄清一下,禁用 DMA 或使用 DMAdm-crypt将在高磁盘流量期间导致 CPU 占用率过高)

  • 问题的关键不在于 WM 臃肿并导致系统变得缓慢(正常使用下它可能完全响应),而是内核在内存不足时没有正确优先考虑应用程序并且必须进入大量交换。我在使用过的每一个桌面 Linux 上都遇到过这个问题,虽然使用更轻的程序或添加更多的内存可能会有所帮助,但它并不能解决问题的根源。 (2认同)