如何优雅地解决此内存问题?


10

我有一台带有交换分区的标准Linux(Debian测试)笔记本电脑。

我做了很多实验。其中一些确实非常消耗内存,Linux默认情况下的行为方式对我来说是个问题...让我们举一个愚蠢的例子:

  1. 坐在笔记本电脑前
  2. 打开一个终端
  3. 类型python,然后a = [0]*100000000

现在很有可能您没有足够的RAM来处理这个大列表。Linux将先填充RAM,然后进行交换,几分钟后,OOM杀手将被触发并杀死(几乎)随机服务,如果希望您在适当的时候按Ctrl + C python,并且如果终端仍然有重点,计算机将再次变得敏感。

我想强制执行一些内存限制,以避免不必要的交换,并拒绝给进程分配比我(在RAM中)更多的内存的权利。如果内存需求低于某个限制或由root要求,则只需杀死除root以外的任何用户最耗费内存的进程。

ulimit -Sv [mem] 我在后面听到!

呵呵!“ cgroups通过使用cgexec!” 有人在第一行说!

是的,您是对的:这些确实是非常好的解决方案。但:

  • 它们不适用于整个系统
  • 限制是按过程设置的
  • 限制是静态的,不考虑可用RAM(AFAIK)的实际数量
  • 这里那里,他们说这些是不是真的很好地解决执行难的限制。

我想要的是内核说:“您属于用户foo(不是root),您使用了大量内存,而我们将用光内存。抱歉,老兄……现在就死了!”

或者:“您到底在干什么?您需要x MB,只有y MB可用。是的,SWAP是空的,但是您不打算使用SWAP来完成您的工作,是吗?不,我说不!你没有记忆!如果你坚持下去,你会死的!


2
已经有中描述的算法,这篇文章这有助于OOM杀手选择正确的过程。更改/proc/sys/vm/overcommit_memory会影响低内存中的内核行为。
jofel

1
是的,但是overcommit_memory特殊文件使用RAM + SWAP作为可用内存。我仍然要交换:)

1
您还需要解释一下这不是它的重复项:unix.stackexchange.com/questions/34334/…,这与您的WRT cgroup和单个用户相矛盾。PS。如果您不想交换,请禁用swap
goldilocks

1
我要交换!我想休眠,我想将未使用的字节存储起来!但是我不希望将使用过的字节存储在那里。关于链接,ulimits是一个坏主意,几乎每个地方都显示出来,因为它是每个进程的限制...我知道cgroups,您知道:)关于,这绝对更好,但缺少更一般的东西:我在谈论笔记本电脑,但我也拥有我们三个人共享的“计算”服务器。如果我对每个用户实施这样的限制,那么我将受到最坏情况的限制,不是吗?

1
cgroup确实适用于您决定将用户的所有进程归为一个单独的组的任何进程,并且它应该执行您想要的操作。
彼得

Answers:


4

有人建议您听见cgroups。好吧,尝试寻求该方向,因为它可以为您提供:

  • 应用于您选择的一组任务(因此不是系统范围的,而是每个过程都没有)
  • 为组设置了限制
  • 限制是静态的
  • 他们可以对内存和/或内存+交换执行硬限制

这样的事情可能使您更接近目标

group limited {
  memory {
    memory.limit_in_bytes = 50M;
    memory.memsw.limit_in_bytes = 50M;
  }
}

这表明该cgroup下的任务最多只能使用50M内存,而最多只能使用50M + swap的内存,因此,当内存已满时,它不会交换,但是如果内存未满,则可以在其中映射一些数据交换,这是可以允许的。

这是cgroup的内存文档的摘录:

通过使用memsw limit,可以避免由于交换不足而引起的系统OOM。


仍然不是我所期望的。但是我期望的和现实之间的差异通常很大:)在这种情况下,我想确保自己不会错过任何类似overcommit_memory内核变量的内容。谢谢你们。

0

我经常遇到相同的问题。我的一般工作流程涉及在MATLAB中进行大量计算。有时我会无意间尝试分配一个超出可用内存量的新变量。系统挂起,我通常必须重新启动计算机才能恢复工作。:P

就我而言,听起来也像您一样,我不太在意将MATLAB使用的内存量限制为静态量-我对没有冻结的计算机很感兴趣,并且我愿意牺牲我的MATLAB过程为了保持系统的响应能力。

受到对此帖子的回应的启发,我编写了以下脚本(我将其称为watch_memory.sh):

#!/bin/bash

MONITOR=$(free | grep 'buffers/cache:')
MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')

MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))

while :; do
    if [ "$MEM_PERC" -gt "95" ]
    then
        kill $1
        echo "$1 killed for using too much memory."
        exit
    fi
    sleep 1

    MONITOR=$(free | grep 'buffers/cache:')
    MEM_USED=$(echo $MONITOR | awk '{ print $3 }')
    MEM_FREE=$(echo $MONITOR | awk '{ print $4 }')
    MEM_PERC=$(( 100*MEM_USED / (MEM_FREE+MEM_USED) ))
done

此脚本每秒检查一次可用内存的百分比。当系统用尽时,您的“替罪羊” pid(作为脚本的参数传递)被杀死。

在不调整脚本优先级的情况下,替罪羊被杀死大约需要10到20秒,但它仍然有效。以负优先级运行脚本会导致违反后立即终止运行(此示例中的11916是我要在内存不足时终止的pid):

sudo nice -n -5 bash watch_memory.sh 11916
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.