이 메모리 문제를 우아하게 해결하는 방법은 무엇입니까?

이 메모리 문제를 우아하게 해결하는 방법은 무엇입니까?

저는 스왑 파티션이 있는 표준 Linux(Debian 테스트) 노트북을 가지고 있습니다.

나는 그것을 가지고 많은 실험을 했습니다. 그 중 일부는 실제로 메모리 집약적이며 Linux가 기본적으로 작동하는 방식이 나에게 문제가 됩니다... 어리석은 예를 들어보겠습니다.

  1. 노트북 앞에 앉아
  2. 터미널 열기
  3. 을 입력 python한 다음a = [0]*100000000

이제 이 큰 목록을 처리할 RAM이 충분하지 않을 가능성이 높습니다. Linux는 RAM을 채운 다음 교체하고 몇 분 후에 OOM 킬러가 트리거되어 (거의) 무작위 서비스를 종료합니다. 적절한 순간에 Ctrl+C를 누르고 python터미널에 여전히 포커스가 있는 경우 , 컴퓨터가 다시 응답합니다.

불필요한 스왑을 방지하고 프로세스가 내가 가지고 있는 것보다 더 많은 메모리(RAM)를 할당할 수 있는 권한을 거부하기 위해 일부 메모리 제한을 적용하고 싶습니다. 메모리 요구 사항이 특정 제한 아래로 떨어지거나 루트에서 요청하는 경우 루트 이외의 사용자에 대해 메모리를 가장 많이 소비하는 프로세스만 종료됩니다.

ulimit -Sv [mem]뒤에서 들었어!

호호! "사용이 cgroups통과되었습니다 cgexec!" 첫 번째 줄에 있는 누군가가 말했습니다!

예, 당신 말이 맞습니다. 이것은 실제로 매우 좋은 솔루션입니다. 하지만:

  • 전체 시스템에 적용되지는 않습니다.
  • 프로세스별로 제한이 설정됩니다.
  • 제한은 정적이며 실제 사용 가능한 RAM(AFAIK) 양을 고려하지 않습니다.
  • 여기그리고거기, 그들은 이것이 엄격한 제한을 시행하기 위한 실제로 좋은 솔루션이 아니라고 말합니다.

내가 원하는 것은 커널이 "당신은 사용자에게 속해 있습니다"라고 말하는 것입니다.부자(루트 아님) 메모리를 많이 사용하고 있어 메모리가 부족해집니다. 미안... 당장 지옥에나 가! "

또는: "대체 뭐하는 거야? 넌 필요해엑스MB만와이MB 사용 가능. 예, SWAP은 비어 있지만 SWAP을 사용하여 더러운 작업을 수행하지는 않을 것입니다. 그렇죠? 아니요, 아니요! 당신에 대한 기억이 없습니다! 계속하면 죽는다! "

답변1

누군가가 당신의 귀에 뭔가를 제안했습니다 cgroups. 글쎄요, 다음을 제공할 수 있으므로 그 방향을 살펴보십시오.

  • 선택한 작업 세트에 적용됩니다(시스템 전체가 아닌 프로세스별).
  • 이 그룹에 제한사항이 설정되었습니다.
  • 한도는 정적입니다.
  • 메모리 및/또는 메모리 + 스왑에 엄격한 제한을 적용할 수 있습니다.

이런 것이 당신을 가져올 수 있습니다목표에 더 가까이 다가가세요:

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

이는 이 cgroup의 작업이 최대 50M 메모리, 50M 메모리 + 스왑까지만 사용할 수 있으므로 메모리가 가득 차면 스왑되지 않지만 메모리가 가득 차지 않으면 일부 데이터가 스왑에 매핑될 수 있음을 보여줍니다. 허용됩니다.

이것은 에서 발췌한 것입니다.cgroup 메모리 문서:

memsw 제한을 사용하면 스왑 공간 부족으로 인한 시스템 OOM을 방지할 수 있습니다.

답변2

나는 종종 같은 문제에 직면합니다. 내 일반적인 작업 흐름에는 MATLAB에서의 많은 계산이 포함됩니다. 때때로 나는 무심코 사용 가능한 메모리 양을 초과하는 새 변수를 할당하려고 시도합니다. 시스템이 중단되고 일반적으로 다시 작업하려면 컴퓨터를 하드 재부팅해야 합니다. :피

내 경우에는 그리고 귀하의 상황도 마찬가지인 것 같습니다. 저는 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(스크립트에 인수로 전달됨)가 종료됩니다.

스크립트 우선순위(niceness)를 조정하지 않으면 희생양이 죽는 데 약 10~20초가 걸렸지만 여전히 작동했습니다. 음수 우선순위로 스크립트를 실행하면 위반 후 즉시 종료됩니다(이 예에서 11916은 메모리가 부족할 경우 종료하려는 pid입니다).

sudo nice -n -5 bash watch_memory.sh 11916

관련 정보