리눅스 free 명령어로 메모리 상태 확인하기
free 명령어를 사용하면 쉽게 메모리 사용량과 여유량 그리고 캐싱으로 사용되는 메모리가 얼마나 있는지 파악할 수 있습니다. 실제 free 명령어는 리눅스 /proc/meminfo에서 메모리 정보를 가져와 보여줍니다. 그럼 free 명령어로 볼 수 있는 메모리 정보와 이와 관련된 meminfo의 값들을 알아보겠습니다.
free 명령어
- [total] : 설치된 총 메모리 크기 / 설정된 스왑 총 크기
- [used] : total에서 free, buff/cache를 뺀 사용중인 메모리. / 사용중인 스왑 크기
- [free] : total에서 used와 buff/cahce를 뺀 실제 사용 가능한 여유 있는 메모리량 / 사용되지 않은 스왑 크기
- [shared] : tmpfs(메모리 파일 시스템), ramfs 등으로 사용되는 메모리. 여러 프로세스에서 사용할 수 있는 공유 메모리
- [buffers] : 커널 버퍼로 사용중인 메모리
- [cache] : 페이지 캐시와 slab으로 사용중인 메모리
- [buff/cache] : 버퍼와 캐시를 더한 사용중인 메모리
- [available] : swapping 없이 새로운 프로세스에서 할당 가능한 메모리의 예상 크기. (예전의 -/+ buffers/cache이 사라지고 새로 생긴 컬럼)
옵션
- [-h] : 사람이 읽기 쉬운 단위로 출력한다.
- [-b | -k | -m | -g] : 바이트, 키비바이트, 메비바이트, 기비바이트 단위로 출력한다.
- [--tebi | --pebi] : 테비바이트, 페비바이트 단위로 출력한다.
- [--kilo | --mega | --giga | --tera | --peta] : 킬로바이트, 메가바이트, 기기바이트, 페타바이트 단위로 출력한다.
- [-w] : 와이드 모드로 cache와 buffers를 따로 출력한다.
- [-c '반복'] : 지정한 반복 횟수 만큼 free를 연속해서 실행한다.
- [-s '초'] : 지정한 초 만큼 딜레이를 두고 지속적으로 실행한다.
- [-t] : 합계가 계산된 total 컬럼줄을 추가로 출력한다.
캐시(Cache)와 버퍼(Buffer)의 차이점
리눅스는 항상 여유 메모리 공간을 Buffer와 Cache로 사용하려고 시도합니다. 메모리에 데이터를 저장해서 느린 디스크로의 접근을 최대한 줄여 성능을 향상 시킵니다.
Buffer는 버퍼 캐시로 디바이스 블록에 대한 메타데이터들을 메모리에 캐싱한 크기입니다. 블록 디바이스로부터 데이터를 읽어오기 위해 필요한 정보들을 메모리에 저장해 둡니다.
Cache는 페이지 캐시와 slab으로 사용중인 메모리 크기입니다.
- 페이지 캐시는 한 번 디스크로 읽어온 데이터를 메모리에 저장하여 같은 데이터를 다시 읽을 때 디스크로 요청하지 않고 메모리에서 바로 읽어올 수 있게 합니다.
- slab은 커널에서 관리하는 커널 오브젝트를 저장하는 단위입니다. 커널은 애플리케이션 할당 단위인 페이지 보다 작은 단위인 slab 단위로 메모리를 사용합니다. 하나의 메모리 페이지에 여러 slab들이 존재할 수 있습니다.
- slab에 파일의 inode나 dentry 정보들을 캐싱할 수 있습니다.
실제로 약 1M 크기의 파일을 생성해 이를 읽으면 cache 크기가 증가하는 것을 볼 수 있습니다.
Cache와 Buffer 중 최근 사용되지 않은 메모리 크기에 대한 자세한 정보는 /proc/meminfo에서 볼 수 있습니다.
위에 보이는 Inactive(anon)와 Inactive(file), SRelaimable이 참조된 지 오래되어 스왑 영역으로 이동하고 그 영역을 새로운 메모리로 할당할 수 있는 크기입니다.
- Inactive(anon)는 익명 메모리중 참조가 적은 메모리 크기입니다.
- Inactive(file)은 페이지 캐시중 참조가 적은 메모리 크기입니다.
- SRelaimable은 slab중 재할당이 가능한 영역입니다.
free 명령어에서 이 값 들을 참조하여 메모리에 캐싱된 데이터들 중 스왑 영역으로 아웃 시키고 메모리를 비워 새로운 할당을 할 수 있는 크기를 free 명령어의 available로 보여주는 것입니다. available은 어디까지나 시스템에서 계산된 예측 크기이니 이 값에 너무 의존해서도 안됩니다.
스왑(swap) 메모리
스왑은 디스크의 일정 부분을 메모리 공간 부족시 메모리처럼 사용하기 위해 설정해둔 공간입니다.
커널은 메모리가 부족한 상황에서는 Buffer와 Cache로 할당된 것 중에 자주 사용 되지 않는 것들을 비우고 메모리에 할당을 하려고 시도합니다. 또한 메모리에 있는 데이터 중 최근 자주 사용되지 않은 데이터를 SWAP 공간으로 이동시킵니다.(SWAP-OUT)
그리고 SWAP으로 옮겨진 데이터를 프로세스가 읽기 위해 메모리로 데이터를 다시 가져옵니다.(SWAP-IN) 이는 디스크로부터 옮겨 졌던 데이터를 다시 메모리로 가져오기 때문에 레이턴시가 길어져 결국 성능 저하로 이어집니다.
일시적인 메모리 사용 증가로 일정 SWAP을 사용하는 상황과 지속적인 메모리 부족으로 인해 SWAP이 커지는 경우를 지속적으로 모니터링 하여 메모리 증설 시점을 고려해야 합니다.
마무리
로드밸런싱이나 워크로드를 분산 배치 시키는 프로그램들은 /proc/meminfo를 참고하여 캐싱 영역을 비워 얼마만큼의 메모리 할당이 가능한지에 대한 정보도 확인합니다. 수동으로 명령어를 이용해 캐싱을 비울 수도 있습니다. 하지만 캐싱을 적절히 사용하는 것이 시스템 성능 향상을 가져올 수 있고 너무 자주 캐싱을 비우면 오히려 성능 저하로 이어질 수 있습니다. 그러니 시스템 특성에 맞춰서 캐싱에 대한 커널 파라미터를 적절히 설정 하는 것에 대한 고민이 필요합니다.
이 게시글이 문제가 될 시, 삭제하겠습니다