리눅스용 메모리 프로파일러, Heaptrack(1/2)

🧐 | 2022-01-19

안녕하세요, 넷마블 TPM실 기술분석팀 추숙입니다.

메모리릭은 우리의 워라밸을 해치는 대표 주자입니다. 윈도우와 리눅스를 구분하지 않고, 예상치 못한 곳에서 돌발 출현해서 우리를 긴장시킵니다. 윈도우 서버에서 메모리릭을 찾기 위해 메모리 프로파일링하는 방법은 워라밸 브레이커, 메모리릭을 찾아라“ 글에서 가볍고 길게 보실 수 있습니다. 이번 글에서는 리눅스에서 메모리를 프로파일링할 때 사용하는 Heaptrack(힙트랙)을 소개합니다.

리눅스용 메모리 프로파일러

윈도우에서 쓰던 비주얼 스튜디오 진단 도구(Visual Studio Diagnostic Tools)만큼은 아니더라도, 최소한 어떤 기능이 있어야 리눅스에서도 편하게 쓸 수 있을까요?

메모리 프로파일러가 갖춰야 할 기능

  • 구동 중인 프로세스에 attach 가능
  • 상대적으로 가볍게 동작
  • GUI 환경 분석 도구

리눅스에서 주로 사용하는 메모리 프로파일러는 Heaptrack(힙트랙), Valgrind(밸그린드), Memleax(멤릭스) 등 3가지가 있습니다. Heaptrack을 상세히 살펴보기 앞서, Valgrind와 Memleax를 간단히 살펴보겠습니다.

Valgrind

  • 애플리케이션 실행부터 attach해서 구동해야 함
  • 매우 무거움. (공식 문서 상 20배 이상 성능 저하). 구동 시간 필요.
  • 32비트 애플리케이션은 사용할 만 함. (64비트 애플리케이션은 도저히 사용 불가)

Memleax

  • 구동 중인 애플리케이션에 attach 가능.
  • attach하는 순간, Valgrind 보다는 가볍게 동작하는 것으로 보임.
  • 자체 버그가 존재하는 듯하며, 쉽게 크래시(Crash) 발생.
  • 크래시 발생 시, 애플리케이션도 동시에 크래시 발생.

메모리 프로파일러가 갖췄으면 했던 기능에 대조해보면, Valgrind와 Memleax는 아쉬운 부분이 있었습니다. 과연 Heaptrack은 어떨까요?

Heaptrack

Heaptrack은 모든 메모리 할당마다 스택 트레이스(Stack Traces) 주석을 붙입니다. 전용 분석 도구를 활용해 힙 메모리(Heap Memory) 프로필도 볼 수 있으므로, 메모리릭이 발생하는 지점을 찾을 수 있습니다.

Heaptrack은 크게 두 부분으로 구성돼 있습니다. 애플리케이션 메모리 사용 데이터를 수집하는 ‘heaptack’과 수집한 데이터를 분석할 수 있도록 GUI 환경으로 표현하는 ‘heaptrack_gui’ 입니다. 만약 GUI 환경이 아니라, 텍스트 형태로 된 보고서를 받고 싶다면 ‘heaptrack_print’를 사용합니다.

프로세스

Heaptrack 동작 프로세스는 분석 타깃 머신 구동으로 시작합니다. 분석 타깃 머신을 구동하면, Heaptrack 수집기를 실행해서 메모리 사용 내역을 수집합니다. 메모리 사용 내역 수집과 분석 프로세스 자체도 리소스를 소모하므로, 분석용 머신을 원격지에 별도로 세팅하고 수집한 데이터를 복사해서 분석하시기를 추천합니다.

분석기 기능

분석기에는 사용률 순 정렬(Top Usage Sort&View) 기능, 프레임 그래프(Frame Graph), 시간순 그래프(Timeline Graph), 시간 구간별 분석 기능(Time Range Analysis) 등 4가지 분석 기능이 있습니다.

사용률 순 정렬 기능은 메모리 사용량순으로 정렬하는 것 이외에도 메모리릭이 의심되는 메모리를 선별해서 정렬하는 기능도 같이 있습니다. 시간 구간별 분석 기능에서 시간은 그래프에 드래그해서 범위를 선택하면 되고, 우클릭을 눌러 필터를 설정하면 해당 범위 내에 있는 메모리 사용량을 재분석한 결과를 볼 수 있습니다.

Heaptrack 설치

이제 Heaptrack을 설치하는 방법을 살펴보겠습니다.

– KDE 소프트웨어로 리눅스 환경에서 구동

– GUI는 윈도우 환경에서 WSL을 활용해 분석기를 쓰도록 설치할 예정

– Heaptrack 소스: https://github.com/KDE/heaptrack.git

수집기 설치

수집기 설치는 CentOS 7 기준으로 설명할 예정입니다. ‘yum’을 활용하는 것이 유리하므로, 라이트(Lite) 버전 OS라면 ‘yum’을 사용할 수 있는 환경을 미리 세팅하는 것이 좋습니다. 또한, 설치한 바이너리를 ‘boost’와 ‘unwind’ 라이브러리와 함께 복사하면 원격지에서도 실행할 수 있습니다.

수집기 설치 전에 아래에 나열한 의존성 패키지를 미리 설치합니다. (대부분 ‘yum’으로 설치할 수 있습니다.)

  • cmake 2.8.9 or higher(빌드용)
  • C++11 컴파일러(g++이나 clang++ 등)
  • zlib
  • libdl / pthread / libc (gcc 설치 시, 대부분 설치됨)
  • libunwind

‘boost’ 관련 라이브러리는 공식 사이트 저장소에서 1.41버전 이상을 받아서 설치하는 것이 좋습니다. 다운로드 이후에 ‘LD_LIBRARY_PATH’로 경로를 지정합니다.

의존성 패키지 준비를 마쳤다면, 소스 폴더로 이동해 아래 명령어를 순서대로 실행합니다.

$ mkdir build
$ cd build
$ cmake ..

‘cmake’를 실행하면, 의존성 검사를 합니다. 아래 문구대로 나오면 설치 준비가 끝난 것입니다.

[root@sqta-test01 build]# cmake ..
-- Boost 1.41.0 found.
-- Found Boost components:
   system;filesystem;iostreams
-- Could NOT find ZSTD (missing: ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
-- Boost 1.41.0 found.
-- Found Boost components:
   iostreams;program_options
-- Could NOT find Qt5 (missing: Qt5_DIR)
-- Could NOT find ECM (missing: ECM_DIR)
-- The following REQUIRED packages have been found:
 
 * Threads
 * ZLIB
 * Libunwind
 * boost_iostreams (required version == 1.76.0)
 * boost_headers (required version == 1.76.0)
 * boost_program_options (required version == 1.76.0)
 * Boost (required version >= 1.41.0)
 
-- The following OPTIONAL packages have not been found:
 * Qt5 (required version >= 5.2.0)
 * ECM (required version >= 1.0.0)
 
-- The following RECOMMENDED packages have not been found:
 * Zstd
   Zstandard offers better (de)compression performance compared with gzip/zlib, making heaptrack faster and datafiles smaller.
 
-- Configuring done
-- Generating done
-- Build files have been written to: /root/util/heaptrack-1.2.0/build

‘REQUIRED packages’에 있는 패키지는 반드시 설치해야 하는 패지지입니다. 만약 누락된 패키지가 있다면, ‘yum’이나 구글링으로 꼭 해소하셔야 합니다.

‘OPTIONAL packages’에 있는 ‘Qt5’와 ‘ECM’은 수집기가 아니라 분석기 GUI 환경을 구성할 때 필요한 패키지입니다. 만약 수집기만 설치하시거나 ‘heaptrack_print’만 사용할 예정이라면 넘기셔도 됩니다.

‘RECOMMENDED packages’에 있는 ‘Zstd’ 라이브러리(링크)는 선택 사항입니다. 사용할 때 수집기와 분석기 성능이 조금 향상됩니다. 없어도 수집기와 분석기 구동에 지장이 없습니다.

이제 ‘build’ 폴더에 ‘Makefile’이 생성됐습니다. ‘make’와 ‘make install’을 실행해 설치하면 됩니다. 이때 권한 문제로 에러가 발생한다면, 루트 계정 또는 ‘sudo’로 실행하면 됩니다. 설치 폴더(기본 위치: /usr/local/bin)에서 ‘heaptrack’과 ‘heaptrack_print’를 볼 수 있다면 빌드가 끝났습니다.

GUI 분석기 설치

GUI 분석기 설치는 WSL로 설치한 우분투(Ubuntu)를 기준으로 설명할 예정입니다. 리눅스에서 직접 X-window로 구동한다면, WSL과 조금 다른 부분이 있을 수 있습니다.

GUI 환경을 위한 의존성 패키지는 상당히 많습니다.

  • cmake 2.8.9 이상(빌드용)
  • C++11 컴파일러(g++이나 clang++ 등)
  • zlib
  • libdl / pthread / libc (gcc 설치 시, 대부분 설치)
  • libunwind
  • Qt5Gui (5.12.8 버전 이상)
  • ECM (1.0.0 버전 이상)
  • KF5I18n
  • KF5ItemModels
  • KF5ThreadWeaver
  • KF5Service (5.68.0 버전 이상)
  • KF5Completion (5.68.0 버전 이상)
  • KF5ItemViews (5.68.0 버전 이상)
  • KF5JobWidgets (5.68.0 버전 이상)
  • KF5Solid (5.68.0 버전 이상)
  • KF5CoreAddons (5.68.0 버전 이상)
  • KF5Auth (5.68.0 버전 이상)
  • KF5Codecs (5.68.0 버전 이상)
  • KF5WidgetsAddons (5.68.0 버전 이상)
  • KF5ConfigWidgets (5.68.0 버전 이상)
  • KF5XmlGui (5.68.0 버전 이상)
  • KF5KIO
  • KF5
  • Qt5Widgets
  • Qt5Test
  • Qt5Core
  • Qt5 (5.10.0 버전 이상)
  • KChart (2.6.0 버전 이상)

의존성 패키지 설치에 어려움을 겪는다면, 레퍼런스 페이지를 참고하면 됩니다. 의존성 패키지를 설치하면서 ‘KDiagram’도 같이 설치하는 것이 좋습니다.

의존성 패키지 준비를 마쳤다면, 소스 폴더로 이동해 아래 명령어를 순서대로 실행합니다.

$ mkdir build
$ cd build
$ cmake ..

‘cmake’를 실행하면, 의존성 검사를 합니다. 아래 문구대로 나오면 설치 준비가 끝난 것입니다.

~/util/heaptrack/build$ cmake ..
-- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found suitable version "1.71.0", minimum required is "1.60.0") found components: system filesystem iostreams container
-- Could NOT find ZSTD (missing: ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
-- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found suitable version "1.71.0", minimum required is "1.41.0") found components: iostreams program_options system filesystem
-- The following OPTIONAL packages have been found:
 * Qt5Gui (required version >= 5.12.8)
 * ECM (required version >= 1.0.0)
 * KF5I18n
 * KF5ItemModels
 * KF5ThreadWeaver
 * KF5Service (required version >= 5.68.0)
 * KF5Completion (required version >= 5.68.0)
 * KF5ItemViews (required version >= 5.68.0)
 * KF5JobWidgets (required version >= 5.68.0)
 * KF5Solid (required version >= 5.68.0)
 * KF5CoreAddons (required version >= 5.68.0)
 * KF5Auth (required version >= 5.68.0)
 * KF5Codecs (required version >= 5.68.0)
 * KF5WidgetsAddons (required version >= 5.68.0)
 * KF5ConfigWidgets (required version >= 5.68.0)
 * KF5XmlGui (required version >= 5.68.0)
 * KF5KIO
 * KF5
 * Qt5Widgets
 * Qt5Test
 * Qt5Core
 * Qt5 (required version >= 5.10.0)
 
-- The following RECOMMENDED packages have been found:
 * KChart (required version >= 2.6.0)
   Required for the heaptrack_gui executable. Get it from the kdiagram module.
 
-- The following REQUIRED packages have been found:
 * Threads
 * ZLIB
 * Libunwind
 * boost_iostreams (required version == 1.71.0)
 * boost_headers (required version == 1.71.0)
 * boost_program_options (required version == 1.71.0)
 * boost_system (required version == 1.71.0)
 * boost_filesystem (required version == 1.71.0)
 * Boost (required version >= 1.41.0)
 * Gettext
 
-- The following RECOMMENDED packages have not been found:
 * Zstd
   Zstandard offers better (de)compression performance compared with gzip/zlib, making heaptrack faster and datafiles smaller.
 
-- Configuring done
-- Generating done

‘OPTIONAL packages’를 모두 설치해야 GUI 환경 분석기를 사용할 수 있으니, 빼먹지 말아야 합니다.

‘RECOMMENDED packages’에 있는 ‘Zstd’ 라이브러리(링크)는 설치하면 성능 향상 효과를 볼 수 있습니다. 하지만, 리눅스 환경에 설치한 수집기 데이터를 윈도우 환경에 설치한 분석기로 연결한 경우에는 제대로 동작하지 않는 버그가 있으므로, 각자 환경을 고려해서 설치하면 됩니다.

이제 ‘build’ 폴더에 ‘Makefile’이 생성됐습니다. ‘make’와 ‘make install’을 실행해 설치하면 됩니다. 이때 권한 문제로 에러가 발생한다면, 루트 계정 또는 ‘sudo’로 실행하면 됩니다. 설치 폴더(기본 위치: /usr/local/bin)에서 ‘heaptrack_gui’와 ‘heaptrack_print’를 볼 수 있다면 빌드가 끝났습니다.

여기까지 Heaptrack을 사용하기 위한 기본 설치 방법이었습니다. 의존성 패키지가 꽤 많으므로 잘 확인하면서 설치해야 합니다. 설치한 Heaptrack 수집기와 GUI 분석기 사용법은 다음 글에서 이어가겠습니다.