DevOps - swap, 메모리 증설의 포인트
메모리가 부족한 경우, 어떻게 확인하고 어떻게 대처할 수 있는가.
1. swap 영역
- 물리 메모리가 부족할 경우를 대비해서 만들어 놓은 대비 공간.
- 물리 메모리가 아니라 디스크의 일부를 메모리처럼 사용하기 위해 만든 공간이므로 메모리에 비해 접근과 처리속도는 현저히 떨어진다. -> 따라서 swap 영역 사용시 시스템의 성능 저하가 발생한다.
swap 정보는 free 명령을 통해 알 수 있다.

좌측 2097148 : 전체 swap 영역의 크기 (KB단위)
0 : 현재 사용 중인 swap 영역의 크기
우측 2097148 : 현재 남아있는 swap 영역의 크기
만약 swap 영역을 사용하고 있다면 시스템 메모리가 부족할 수 있다는 의미이므로 swap이 사용된다면 어떤 프로세스가 swap을 사용하는지 확인해 볼 필요가 있다.

확인을 위해서는 /proc/<pid>/smaps 를 참조하면 된다. 해당 파일에는 메모리 정보가 저장되어 있다.

추가로 특정 프로세스가 사용하는 전체 swap 영역에 대한 정보가 필요할 경우에는 /proc/<pid>/status 파일을 참조하면 된다.
이외에 전체 프로세스별 사용 중인 swap 영역의 크기를 확인하고 싶다면 smem을 사용하면 된다.
2. 버디 시스템
swap이 메모리가 부족할 때 사용된다면, 메모리가 부족한 상황은 어떤 상황일까
먼저 커널이 메모리를 할당하는 과정을 보면, '버디 시스템'을 통하는 것을 알 수 있다.
'버디시스템'이란 물리 메모리를 연속된 메모리 영역으로 관리하는 것이다. 이로써 메모리의 단편화를 막고 프로세스의 요청에 더 빠르게 응답할 수 있다.

각 행은 2배수로, 위 DMA절에서 메모리 가용량을 확인해보면
4KB X 1 + 8KB X 1 + 16KB X 1 + 64KB X 2 + 128KB X 1 + 256KB X 1 + 1024KB X 1 + 2048KB X 1 + 4096KB X 4 와 같다.
이 정보는 free 명령의 mem 결과와 유사한데, 프로세스가 메모리를 할당 받으면 buddyinfo의 내용도 변경된다.
3. 메모리 재할당 과정

커널에서의 메모리 재할당은 다음 두가지 로직으로 처리된다.
1) 커널이 사용하는 캐시 메모리의 재할당 (성능 저하 x)
- 사용하지 않는 메모리를 캐시 용도로 사용하면 시스템 성능이 전반적으로 향상되지만 정작 프로세스가 메모리를 필요로 할 때 사용할 메모리가 부족해질 수 있다.
이 때 메모리 재할당이 일어나며 커널은 캐시용 메모리를 사용해제하고 가용 메모리 영역으로 돌린 후 프로세스가 사용할 수 있도록 재할당한다.
2) swap을 사용하는 재할당 (성능 저하 o)
- 위의 캐시용 메모리 외에는 커널이 임의로 메모리를 해제하거나 재할당할 수 없다.
이 때 캐시용 메모리 외에도 메모리가 필요하다면 swap을 사용하게 된다.
커널은 프로세스가 사용하는 메모리 중 Inactive 메모리를 골라 swap영역으로 이동하여 사용한다.
그러나 swap 영역으로 읽거나 쓰는 작업이 디스크에서 일어나기 때문에 시스템 성능이 저하된다.
4. vm.swappiness와 vm.vfs_cache_pressure
이 두 파라미터로는 커널에서 일어나는 캐시 활용과 메모리 재할당 과정을 사용자가 원하는 형태로 조절할 수 있도록 해준다.
vm.swappiness)
메모리가 부족한 상황에 캐시를 비우느냐 or 특정 프로세스 메모리 영역을 swap으로 옮기느냐 결정
값이 커지면 swap 이동을 더 빨리 진행하고 작아지면 캐시를 비우는 작업을 최대한 진행한다.
vm.vfs_cache_pressure)
커널이 메모리를 재할당할 때 디렉터리나 inode에 대한 캐시를 재할당하려는 경향 조절
캐시를 재할당할지 결정했을 때 -> PageCache를 더 많이 재할당할지 or 디렉터리나 inode 캐시를 더 많이 재할당할지 결정
값이 커지면 더 많은 dentry cache가 반환
5. 메모리 증설의 포인트
만약 시스템이 swap 영역을 사용한다면 어떻게 대처해야 할까?
상황에 따라 메모리를 증설해야할 수도 아닐 수도 있다. 증설 여부를 정하기 위해서는 누수가 일어나는지 먼저 체크해야한다.
1. 메모리의 사용량이 선형적으로 증가하는 경우
-> 메모리 누수 의심 (pmap 명령어 등으로 해당 프로세스가 사용하는 힙 메모리 영역의 변화를 살펴보자)
2. 순간적으로 메모리 사용량이 폭증하는 경우
-> 메모리 증설이 도움이 될 수 있음
6. Case Study - gdb를 이용하여 메모리 누수 잡기
메모리 누수가 의심 될 때 gdb와 같은 디버깅 도구가 허용된다면 늘어나고 있는 힙 메모리 영역에 메모리 덤프를 생성하고 어떤 로직에서 사용한 메모리 영역이 해제되지 않았는지 확인할 수 있다.
이를 통해 메모리 누수가 발생하는 로직을 확인하고 수정하면 메모리 누수를 해결할 수 있다.