자바 컨테이너 애플리케이션 메모리 분석

컨테이너 애플리케이션의 경우, 메모리 남용으로 인한 문제를 찾기가 어렵습니다. 사용량이 컨테이너 메모리 제한을 초과하면 애플리케이션이 소리 없이 실패할 수 있으며 아무런 흔적도 남기지 않습니다.

이 글에서는 자바 컨테이너 애플리케이션에서 메모리 소비 원인을 파악하는 데 사용할 수 있는 몇 가지 기술에 대해 살펴보겠습니다.

메모리 유형

일반적인 자바 애플리케이션의 메모리는 힙과 비힙으로 넓게 나눌 수 있습니다. 힙 메모리는 자바 애플리케이션을 시작할 때 관련 JVM 매개변수를 제공함으로써 설정할 수 있습니다.

비힙 메모리는 JVM 자체 또는 JNI(Java Native Interface)를 사용하여 애플리케이션 내에서 사용되는 모든 라이브러리에 의해 사용되는 네이티브 메모리로 구성됩니다.

방법

힙 메모리의 경우 힙 덤프를 취해 힙 덤프 분석 도구를 사용하여 분석할 수 있습니다. 힙 덤프 분석을 위한 최고의 도구 중 하나는 이클립스 MAT입니다.

자바는 네이티브 메모리 추적을 활성화함으로써 네이티브 메모리 할당을 추적하는 메커니즘을 제공하지만, 모든 네이티브 라이브러리에 의해 할당된 메모리를 밝힐 수는 없습니다.

Jemalloc는 네이티브 라이브러리에 의해 할당된 메모리를 추적하는 데 사용할 수 있는 유틸리티입니다. 네이티브 메모리는 malloc이라는 기본 메모리 할당자를 사용하여 할당됩니다. Jemalloc은 메모리 할당 추적을 활성화할 수 있는 범용 malloc 구현으로, 모든 네이티브 메모리 할당을 추적하고 힙 프로파일 덤프를 생성합니다.

이러한 힙 프로파일은 Jeprof 유틸리티를 사용하여 분석할 수 있습니다. Jeprof는 애플리케이션의 함수에 의해 사용되는 메모리를 강조 표시하는 힙 할당 보고서를 생성합니다.

분석

다음은 샘플 컨테이너 Java 애플리케이션의 메모리 분석입니다. 이 애플리케이션은 네이티브 메모리 사용을 활성화하기 위해 샘플 Tensorflow 모델을 로드하고 Docker 컨테이너에서 실행됩니다.

다음은 Docker 메모리 소비입니다. 254MB입니다. 메모리 소비의 근원을 확인해 보겠습니다.

총 메모리

애플리케이션 프로세스가 사용하는 총 메모리에 대한 감을 잡기 위해 Resident Set Size (RSS)를 확인할 수 있습니다. 이는 메인 메모리 또는 RAM에 있는 총 확보된 메모리입니다. top, ps 또는 pmap과 같은 여러 유틸리티를 사용하여 이를 확인할 수 있습니다.

RSS 확인은 사용량의 근본 원인을 명확히 하는 데 도움이 되지 않습니다. 예제 애플리케이션에서 아래 명령어를 사용하면 전체 RSS는 376MB입니다.

Shell

 

ps --no-header -o rss $(pidof java)

힙 분석

아래는 eclipse MAT 도구에 의해 생성된 힙 메모리 소비입니다. 보관된 힙의 전체 크기는 2.2MB로, Docker에 의해 표시된 전체 메모리 소비보다 훨씬 작으며, 이는 비힙 영역에서의 소비가 주요임을 나타냅니다.

네이티브 메모리 분석

아래 명령어를 사용하여 네이티브 메모리 요약을 검토하면 전체 메모리 사용량은 약 99MB로 보입니다. 그러나 이 값은 전체 메모리 소비보다 작으며, 문제의 근본 원인을 정확히 식별할 수 없습니다.

Shell

 

jcmd $(pidof java) VM.native_memory \
    | grep -P "Total.*committed=" \
    | grep -o -P "(?<=committed=)[0-9]+(?=KB)"

오프-힙 메모리 분석

Jemalloc과 Jeprof를 사용한 분석에 따르면 네이티브 메모리 사용은 주로 Tensorflow 라이브러리에 의해 발생하며, 총 소비량은 약 112MB입니다. 

이러한 통찰은 네이티브 메모리 사용의 원천을 명확히 보여주며, 과도한 소비를 줄이기 위해 추가적으로 조사할 수 있습니다.

결론

자바 메모리 분석은 특히 컨테이너 기반 애플리케이션에서 중요합니다. 애플리케이션에서 메모리 소비의 원천을 알고 있다면 메모리 요구를 이해하고, 불필요한 소비를 제거함으로써 애플리케이션 비용을 절감할 수 있습니다.

메모리 소비를 확인할 때는 모든 유형의 메모리와 그 원천을 명확히 해야 합니다. 힙 덤프 분석은 힙 메모리 소비 원천을 명확히 할 수 있으며, Jemalloc과 Jeprof는 네이티브 메모리 소비 원천을 명확히하는 데 유용합니다.

Sample Application Code Link

https://github.com/parveensaini/JavaContainerMemoryAnalysis

Source:
https://dzone.com/articles/java-container-application-memory-analysis