사용 가능한 스왑 공간이 있는데도 서버에 메모리가 부족합니다.
왜?
다음과 같이 재현할 수 있습니다.
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를 살펴보는 것이 더 안전해 보입니다.