메모리가 부족하지만 스왑 영역을 사용할 수 있습니다.

메모리가 부족하지만 스왑 영역을 사용할 수 있습니다.

사용 가능한 스왑 공간이 있는데도 서버에 메모리가 부족합니다.

왜?

다음과 같이 재현할 수 있습니다.

eat_20GB_RAM() {
  perl -e '$a="c"x10000000000;print "OK\n";sleep 10000';
}
export -f eat_20GB_RAM
parallel -j0 eat_20GB_RAM ::: {1..25} &

문제가 해결되면(즉, 모든 프로세스가 절전 모드로 전환됨) 몇 가지를 더 실행합니다.

parallel --delay 5 -j0 eat_20GB_RAM ::: {1..25} &

안정되면(즉, 모든 프로세스가 절전 모드로 전환) 약 800GB RAM/스왑 공간이 사용됩니다.

$ free -m
              total        used        free      shared  buff/cache   available
Mem:         515966      440676       74514           1         775       73392
Swap:       1256720      341124      915596

몇 번 더 실행하면 다음과 같습니다.

parallel --delay 15 -j0 eat_20GB_RAM ::: {1..50} &

나는 이해하기 시작했다:

Out of memory!

분명히 교환이 가능하더라도.

$ free
              total        used        free      shared  buff/cache   available
Mem:      528349276   518336524     7675784       14128     2336968     7316984
Swap:    1286882284  1017746244   269136040

왜?

$ cat /proc/meminfo 
MemTotal:       528349276 kB
MemFree:         7647352 kB
MemAvailable:    7281164 kB
Buffers:           70616 kB
Cached:          1503044 kB
SwapCached:        10404 kB
Active:         476833404 kB
Inactive:       20837620 kB
Active(anon):   476445828 kB
Inactive(anon): 19673864 kB
Active(file):     387576 kB
Inactive(file):  1163756 kB
Unevictable:       18776 kB
Mlocked:           18776 kB
SwapTotal:      1286882284 kB
SwapFree:       269134804 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:      496106244 kB
Mapped:           190524 kB
Shmem:             14128 kB
KReclaimable:     753204 kB
Slab:           15772584 kB
SReclaimable:     753204 kB
SUnreclaim:     15019380 kB
KernelStack:       46640 kB
PageTables:      3081488 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    1551056920 kB
Committed_AS:   1549560424 kB
VmallocTotal:   34359738367 kB
VmallocUsed:     1682132 kB
VmallocChunk:          0 kB
Percpu:           202752 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
DirectMap4k:    12251620 kB
DirectMap2M:    522496000 kB
DirectMap1G:     3145728 kB

답변1

/proc/meminfo찾기 전에 :

CommitLimit:    1551056920 kB
Committed_AS:   1549560424 kB

제출 한도에 도달했습니다.

메모리 오버커밋을 비활성화하면(OOM 킬러를 피하세요) 통과:

echo 2 > /proc/sys/vm/overcommit_memory

그런 다음 커밋 제한은 다음과 같이 계산됩니다.

2   -   Don't overcommit. The total address space commit
        for the system is not permitted to exceed swap + a
        configurable amount (default is 50%) of physical RAM.
        Depending on the amount you use, in most situations
        this means a process will not be killed while accessing
        pages but will receive errors on memory allocation as
        appropriate.

(에서:https://www.kernel.org/doc/Documentation/vm/overcommit-accounting)

다음과 같은 방법으로 전체 메모리를 사용할 수 있습니다.

echo 100 > /proc/sys/vm/overcommit_ratio

물리적 RAM과 스왑이 모두 예약되면 메모리 부족 상황이 발생합니다.

이 경우 이름은 overcommit_ratio약간 오해의 소지가 있습니다. 아무 것도 과장하지 않습니다.

이 설정을 사용하더라도 스왑이 소진되기 전에 메모리 부족이 발생할 수 있습니다. malloc.c:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>

void main(int argc, char **argv) {
  long bytes, sleep_sec;
  if(argc != 3) {
    printf("Usage: malloc bytes sleep_sec\n");
    exit(1);
  }
  sscanf(argv[1],"%ld",&bytes);
  sscanf(argv[2],"%ld",&sleep_sec);
  printf("Bytes: %ld Sleep: %ld\n",bytes,sleep_sec);
  if(malloc(bytes)) {
    sleep(sleep_sec);
  } else {
    printf("Out of memory\n");
    exit(1);
  }
}

다음으로 컴파일:

gcc -o malloc malloc.c

실행 방법(10초 동안 1GB 예약):

./malloc 1073741824 10

이 명령을 실행하면 스왑이 가능한 경우에도 OOM이 표시될 수 있습니다.

# Plenty of ram+swap free before we start
$ free -m
              total        used        free      shared  buff/cache   available
Mem:         515966        2824      512361          16         780      511234
Swap:       1256720           0     1256720

# Reserve 1.8 TB
$ ./malloc 1800000000000 100 &
Bytes: 1800000000000 Sleep: 100

# It looks as if there is plenty of ram+swap free
$ free -m
              total        used        free      shared  buff/cache   available
Mem:         515966        2824      512361          16         780      511234
Swap:       1256720           0     1256720

# But there isn't: It is all reserved (just not used yet)
$ cat /proc/meminfo |grep omm
CommitLimit:    1815231560 kB
Committed_AS:   1761680484 kB

# Thus this fails (as you would expect)
$ ./malloc 180000000000 100
Bytes: 180000000000 Sleep: 100
Out of memory

따라서 free실제로는 올바른 작업을 수행하는 경우가 많지만 CommitLimit 및 Comfilled_AS를 살펴보는 것이 더 안전해 보입니다.

관련 정보