리눅스 메모리 available 이 free 보다 왜 낮을까 ?
free 명령어 결과에서 free 는 아예 미사용중인 메모리 공간을 뜻하고
available 은 유저가 할당 가능한 메모리 공간 추정치(estimate) 값 입니다.
여기서 오해하지 말아야할 가장 중요한것은 free 메모리라고 해서 모두 "유저가 할당 가능한 메모리" 인것은 아닙니다.
available 의 정확한 계산법은 아래와 같습니다. (아래 참고자료 커널소스코드 링크 적어 두었습니다)
available = free 메모리 - (totalreserve_pages 시스템 예약 메모리) + (buff/cache 약 1/2) + (reclaimable slab 해지 가능한 커널 메모리 약 1/2)
(질문 1) available 메모리 공간(예: 100MB)이 free 메모리 공간(예: 5GB) 보다 낮을 수 있나요 ?
예, available 이 free 보다 더 낮을 수 있습니다.
free 메모리 라고 해서 모두다 "유저가 할당 가능한 메모리" 인것은 아니기 때문입니다.
available 메모리를 계산할때 유저가 할당 불가능하다고 제외하는 영역은 시스템 예약 메모리(totalreserve_pages) 입니다.
이는 /proc/sys/vm/lowmem_reserve_ratio 와 /proc/zoneinfo 안의 high 값(워터마크)에 의해서 결정되며 두개의 값이 높진않은지 확인이 필요합니다.
$ cat /proc/sys/vm/lowmem_reserve_ratio 256 256 32 1
위 처럼 lowmem_reserve 가 많이 잡히게 높은 커널 설정이 되어있는지 확인하거나
아래처럼 zone 별로 (예: Normal 존) high 수치를 살펴보고 원인 파악을 해볼 수 있습니다.
$ cat /proc/zoneinfo | grep -A 9 "Normal" Node 0, zone Normal pages free 177936 min 15661 low 19576 high 23491 spanned 3807232 present 3807232 managed 3736157 protection: (0, 0, 0, 0, 0) nr_free_pages 177936
(질문 2) free 메모리가 남아있는 상태임에도 불구하고 기존 메모리(페이지)가 swap 으로 전환 될 수 있나요 ?
예, free 메모리가 남아있는 상태임에도 불구하고 페이지가 swap 으로 전환 될 수 있습니다.
free 메모리가 남아있더라도 available 이 0 이라면(유저가 할당가능한 메모리가 없을때)
할당가능한 메모리가 없기때문에 여유공간을 만들어 내기위해
커널이 내부적으로 기존에 사용하던 페이지를 회수(page reclaim)하여 메모리 내용이 swap로 전환 될 수 있습니다.
(질문 3) sync; echo 3 > /proc/sys/vm/drop_cashes 명령어를 입력해도 available 은 변화가 없을 수 있나요 ?
예, sync 와 drop_caches 를 하더라도 available 수치는 큰 변화가 없을 수 있습니다.
$ sync $ echo 3 > /proc/sys/vm/drop_cashes
sync 는 Dirty 캐시들을 모두 Clean 캐시로 만들지 drop_caches 처럼 메모리상에서 해지 하지는 않습니다.
반면 drop_caches 는 메모리 상에 있는 캐시(미리 읽어둔 디스크 블록) 중에서도
Dirty 캐시(디스크와 달라진 캐시)는 건드리지 않고 Clean 캐시(디스크와 동일한 캐시)만 메모리 상에서 해지(free)합니다.
위 동작을 요약하면 sync 는 "Dirty Caches -> Clean Caches" 이고
drop_caches 는 "Clean Caches => 메모리 해지 => (미사용)free 메모리 증가" 입니다.
물론 sync와 drop_caches 통해서 buff/cache 영역을 줄이고 나면 free 메모리도 상승하고 available 도 상승하는게 "일반적" 입니다.
하지만 반복해서 답변드리는것 처럼 "유저가 할당 불가능한 메모리(시스템 예약 메모리)가 클 경우" 에는 available 수치가 낮게 (예: 100MB) 나올 수 있습니다.
* 답변 참고자료(리눅스 커널 소스 코드) :
free 보다 available 수치가 낮은 이상현상에 대해서 리눅스 커널 소스코드 분석결과로 추가설명드리겠습니다.
현재 free 명령어는 https://gitlab.com/procps-ng/procps 오픈소스 프로젝트에서 소스코드가 개발되고 있고
free 명령어 코드를 살펴보게 되면 /proc/meminfo 안에서 정보를 가져오는것을 확인할 수 있습니다.
/proc/meminfo 는 리눅스 커널 소스코드 안에서 관리되는 특수파일이고 보통 proc 밑의 파일들은
커널 소소코드 fs/proc 폴더 밑에서 관리되고 /proc/meminfo 는 커널 소스코드 아래 와같이
fs/proc/meminfo.c 에서 확인가능합니다.
https://github.com/torvalds/linux/blob/master/fs/proc/meminfo.c#L56
/proc/meminfo 의 MemAvailable 값을 계산하는 코드는
mm/show_mem.c 에서 si_mem_available 함수를 통해서 확인가능합니다.
(참고: 리눅스 커널버전 v4.5 이상이면 available 계산법은 거의 동일합니다.)
https://github.com/torvalds/linux/blob/master/mm/show_mem.c#L32-L72
아래는 MemAvailable 이 처음 만들어진(2014년 1월) 커밋 입니다. (커널 v3.14 부터 포함)
https://github.com/torvalds/linux/commit/34e431b0ae39
long si_mem_available(void) { long available; unsigned long pagecache; unsigned long wmark_low = 0; unsigned long reclaimable; struct zone *zone; for_each_zone(zone) wmark_low += low_wmark_pages(zone); /* * Estimate the amount of memory available for userspace allocations, * without causing swapping or OOM. */ available = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages; /* * Not all the page cache can be freed, otherwise the system will * start swapping or thrashing. Assume at least half of the page * cache, or the low watermark worth of cache, needs to stay. */ pagecache = global_node_page_state(NR_ACTIVE_FILE) + global_node_page_state(NR_INACTIVE_FILE); pagecache -= min(pagecache / 2, wmark_low); available += pagecache; /* * Part of the reclaimable slab and other kernel memory consists of * items that are in use, and cannot be freed. Cap this estimate at the * low watermark. */ reclaimable = global_node_page_state_pages(NR_SLAB_RECLAIMABLE_B) + global_node_page_state(NR_KERNEL_MISC_RECLAIMABLE); reclaimable -= min(reclaimable / 2, wmark_low); available += reclaimable; if (available < 0) available = 0; return available; }
위 코드 중에서 볼 수 있는것처럼 available 수치는 때에 따라서 음수가 될 가능성이 있습니다.
일반적인 상황은 아니고 free 수치 보다 available 수치가 낮은 경우라고 볼 수 있습니다.
if (available < 0) available = 0;
그렇다면 왜 available 이 free 보다 낮을 수 있을까 분석해 본다면 available 수치를 계산하는 내용을 좀더 살펴볼 필요가 있습니다.
available 수치는 기본적으로 Free 페이지를 기반으로 구성됩니다. 하지만 추가적으로 더해지는것(+)과 빼지는것(-)이 존재하는데요.
본 주제는 빼지는것(-)이 중요한 포인트 이기때문에 살펴보자면 총 3가지가 있습니다.
totalreserve_pages 와 min(pagecache / 2, wmark_low) 그리고 min(reclaimable / 2, wmark_low) 입니다.
available = global_zone_page_state(NR_FREE_PAGES) - totalreserve_pages;
위 코드에서 확인 가능하듯이 availble은 총 free 양에서 totalreserve_pages 을 제외 합니다.
이 부분이 현재 Free 보다 Available 수치가 낮은현상의 원인으로 유력합니다.
(참고: min(pagecache / 2, wmark_low) 와 min(reclaimable / 2, wmark_low) 은 빼지는것(-)은 맞으나 결국엔 available 수치를 free 보다 낮추는지는 못합니다)
totalreserve_pages은 시스템상에서 확보해두는 예약된 메모리 총 공간을 뜻합니다.
2가지 메모리 공간이 합쳐져서 totalreserve_pages(= lowmem_reserve + water mark(high))이 됩니다.
* 참고: https://github.com/torvalds/linux/blob/master/mm/page_alloc.c#L5761-L5794
먼저 lowmem 은 Zone 별로 최소한의 예약된 시스템 메모리 공간입니다.
$ cat /proc/sys/vm/lowmem_reserve_ratio 256 256 32 32 0 0
위와 같은 lowmem_reserve_ratio 값(예: 256 이면 1/256 으로 "0.39%" 를 뜻합니다.)이고 해당 값을 토대로 최소한의 (시스템 활용목적) 예약된 메모리 공간(lowmem_reserve)을 마련해둡니다. 그리고 watermark 는 메모리 공간이 부족할때 활용되는 기준으로 보통 high,low,min 등이 존재하고
메모리 공간이 부족해서 swapping 이 동작하는 기준이 low 이고 다시 메모리 여유공간이 확보가 되어 swapping 을 멈추는 기준이 high 입니다.
available 수치는 유저가 (Swap 없이) "사용가능한 메모리 공간" 이기 때문에 (만약 swapping 이 시작되었다면 high 수치까지는 메모리 공간이 확보되어야 swapping 을 멈추기 때문에) high 수치 까지 totalreserve_pages 값에 포함이 됩니다. 따라서 available 수치를 계산할때 free 보다 작아지는 경우는
Available = Free 메모리 공간 - ( lowmem_reserve(예약된 시스템 메모리) + watermark(high) )
위의 정리 처럼 lowmem_reserve 가 높거나 watermark "high" 수치가 높은 경우라고 결론 내릴 수 있습니다.
lowmem_reserve 가 많이 잡히게 높은 커널 설정이 되어있는지 확인하거나
/proc/zoneinfo 의 high 수치를 살펴보고 원인 파악을 해볼 수 있습니다.
본내용의 대한 리얼리눅스 관련 강의로는 리눅스 커널 중급A 강의를 추천드립니다.
https://reallinux.co.kr/course/linux_kernel_a