리눅스 메모리 분석, 파이썬 서버를 통해 메모리 사용량의 비밀을 파헤치다!

by DD
2개월 전
조회수 16

Node.js 서버의 메모리 사용량 급증 문제를 해결하기 위해, 저자는 파이썬 http.server를 활용하여 메모리 분석을 시도함.

`/proc/pid/maps`를 통해 프로세스의 가상 메모리 맵(Virtual Memory Map)을 분석하고, ELF 바이너리, 동적 링커, 공유 라이브러리, 익명 메모리 등 다양한 메모리 관리 개념을 설명함.

Rss(Resident Set Size)Pss(Proportional Set Size)의 차이점을 통해 공유 메모리 사용량을 파악하고, 메모리 사용량의 정확한 의미를 이해하는 것이 중요함을 강조함.

메모리 할당자(Allocator)와 커널 간의 불일치로 인해 메모리가 반환되지 않는 현상, 즉 메모리 누수(Memory Leak)의 원인을 분석하고, 해결 방안에 대한 통찰력을 제공함.

/proc/pid/maps를 이용한 메모리 분석

저자는 `/proc/pid/maps`를 사용하여 프로세스의 가상 메모리 맵을 분석하는 방법을 제시한다. 각 라인은 가상 메모리 영역을 나타내며, 주소 범위, 권한, 오프셋, 장치, inode, 파일 이름 등의 정보를 포함한다. 이를 통해 실행 파일, 공유 라이브러리, 익명 메모리 등 다양한 메모리 영역(Memory Region)의 할당과 사용을 추적할 수 있다. 특히, ELF 바이너리의 LOAD 세그먼트(LOAD Segment)와 VMA(Virtual Memory Area) 간의 관계를 설명하며, 실행 파일의 메모리 구조를 이해하는 데 도움을 준다.

ELF 바이너리(ELF Binary)와 동적 링커(Dynamic Linker)

분석에서는 ELF 바이너리의 구조와 동적 링커의 역할을 자세히 다룬다. ELF(Executable and Linkable Format) 바이너리는 실행 파일의 형식을 정의하며, LOAD 헤더(LOAD Header)는 커널에게 파일의 어떤 부분을 메모리에 매핑할지 지시한다. 또한, 동적 링커는 공유 라이브러리를 로드하고 심볼을 해결하는 역할을 수행한다. 특히, `readelf -l` 명령어를 사용하여 ELF 바이너리의 정보를 확인하고, INTERP 헤더(INTERP Header)를 통해 동적 링커의 위치를 파악하는 방법을 제시한다. 이를 통해 실행 파일의 의존성(Dependency)을 이해하고, 런타임 환경을 분석할 수 있다.

공유 라이브러리(Shared Library)와 페이지 캐시(Page Cache)

저자는 공유 라이브러리의 동작 방식과 페이지 캐시의 중요성을 설명한다. 공유 라이브러리는 여러 프로세스에서 공유하여 사용될 수 있으며, 커널은 페이지 캐시(Page Cache)에 라이브러리의 내용을 저장하여 메모리 사용량을 최적화한다. 여러 프로세스가 동일한 라이브러리를 사용하는 경우, 각 프로세스는 페이지 캐시의 동일한 물리적 프레임을 공유한다. Rss(Resident Set Size)는 프로세스가 사용하는 물리적 메모리의 총량을 나타내지만, 공유된 페이지는 여러 프로세스에 중복 계산될 수 있다. Pss(Proportional Set Size)는 이러한 공유 메모리를 각 프로세스에 분산하여 계산하여, 보다 정확한 메모리 사용량을 파악할 수 있도록 돕는다.

익명 메모리(Anonymous Memory)와 메모리 할당자(Memory Allocator)

익명 메모리의 개념과 메모리 할당자의 역할을 설명한다. 익명 메모리는 파일에 의해 뒷받침되지 않는 메모리 영역으로, 힙(Heap)과 `mmap(MAP_ANONYMOUS)`을 통해 할당된다. 익명 페이지(Anonymous Page)는 스왑(Swap) 공간에 저장될 수 있으며, 메모리 부족 시 성능 저하를 유발할 수 있다. 또한, 메모리 할당자는 프로세스 내에서 메모리 할당 및 해제를 관리하며, 커널과 할당자 간의 불일치로 인해 메모리 누수가 발생할 수 있다. 예를 들어, 할당자가 메모리 공간을 재사용하지만, 커널은 해당 페이지를 여전히 사용 중으로 인식하는 경우가 있다. 이러한 불일치는 Rss(Resident Set Size)가 감소하지 않는 원인이 된다.

가상 메모리(Virtual Memory)와 물리 메모리(Physical Memory)

가상 메모리와 물리 메모리의 관계를 설명하며, VSZ(Virtual Size)Rss(Resident Set Size)의 차이점을 강조한다. VSZ는 프로세스가 사용할 수 있는 가상 주소 공간의 크기를 나타내며, Rss는 실제로 물리 메모리에 상주하는 페이지의 크기를 나타낸다. 커널은 가상 주소 공간을 할당하지만, 실제로 메모리를 할당하는 것은 페이지 폴트(Page Fault)가 발생할 때이다. 즉, 가상 메모리 공간은 존재하지만, 물리 메모리가 할당되지 않은 상태일 수 있다. 이러한 지연 할당(Demand Paging)은 메모리 사용량을 효율적으로 관리하는 데 기여하지만, 메모리 사용량 분석 시 VSZ와 Rss의 차이를 이해하는 것이 중요하다.

Where is every byte?