워라밸 브레이커, 메모리릭을 찾아라(1/4)

| 2021-11-26

대용량 애플리케이션에서 메모리릭을 찾아보자

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

이 글에서 몇몇 도구를 활용해 메모리릭을 탐지했던 제 경험을 공유하려고 합니다. 비슷한 작업을 하시는 분들께 꼭 도움이 됐으면 좋겠습니다.

메모리릭

메모리릭(Memory Leak, 메모리 누수)이란 무엇일까요? 메모리릭은 개발자가 의도하지 않은 메모리를 점유하고 있는 현상을 말합니다. 메모리릭은 때를 가리지 않고 서비스 장애를 유발해, 작업자를 끊임없이 괴롭힙니다. 그래서 메모리릭을 찾을 때는 가지고 있는 모든 것을 활용해 수단과 방법을 가리지 않고 반드시 찾아야 합니다. 그럼에도 불구하고 메모리릭을 찾지 못한다면, 최후의 수단으로 광범위한 소스에 로그나 시스템 지표를 추가하며 분석하기를 반복할 수밖에 없습니다. 

  • 윈도우 환경에서 구동하는 C++ 대용량 서버 메모리릭 탐지 경험입니다.
  • WinDbg를 사용하는 것이 주된 내용입니다. 상황에 따라 GFlags도 사용합니다.
  • 전체 메모리를 수치화된 데이터로 추출해 비교 분석하는 수동 노가다 탐지 방법입니다.

메모리 프로파일러

메모리 프로파일러는 메모리 사용영역을 탐지하고 객체별 사용 빈도와 데이터 라이프 사이클 같은 데이터를 자동으로 수집하는 툴을 말합니다. 즉, 메모리 문제 분석을 위한 일종의 헬퍼라고 할 수 있습니다. 이런 메모리 프로파일러 툴들은 수요가 높아, 다양한 회사나 그룹에서 개발하고 있습니다. 그 중, 몇 가지를 추려봤습니다.

메모리 프로파일러 – MTuner, Visual Studio, OneAPI

오픈소스 프로젝트 중에는 MTuner가 있습니다. 상용 프로그램 중에는 비주얼 스튜디오(Visual Studio)에 진단 도구(Diagonostic tools)라는 분석 기능과 인텔에서 제공하는 Inspector 등이 있습니다. 이외에도 여러 툴이 있으니 각자 프로젝트에 적합한 것을 찾아서 활용하면 됩니다.

메모리 프로파일러 특징

구동 성능에 매우 많은 영향을 줍니다

메모리 프로파일러는 공식 매뉴얼에도 나와 있고 실제 경험상에서 느낄 수 있지만, 프로세스 구동에 영향을 줍니다. 데이터를 수집하고 분석하기 위해 어쩔 수 없이 추가 리소스를 사용해야 할 수밖에 없습니다. 그래서 구동 성능에 매우 많은 영향을 준다는 것을 감안해야 합니다. 체감상 20배 이상이라고 보였었는데, 실제 얼마나 영향이 가는지는 각자 프로젝트에서 직접 테스트해보시면 느끼실 수 있으리라 생각합니다. 정확한 수치로는 산출하기 힘들지만, 매우 느려진다는 것은 분명합니다.

추가 리소스 사용이 있을 수 있습니다

메모리 프로파일러로 인해 메모리 사용량이 증가합니다. 툴마다 추가되는 사용량은 다릅니다만, 앞서 소개했던 mtuner의 경우에는 수집과 분석 과정 각각에 별도 리소스를 할당해서 사용합니다. 애플리케이션이 사용하는 메모리 대비 2배 이상을 분석 시에 사용합니다. 

이런 제약조건으로 인해, 메모리 프로파일러를 구동해보기 위해서는 충분한 스펙과 리소스가 있는 머신을 준비해야 테스트할 수 있습니다.

MMORPG에서 사용하는 메모리

MMORPG 서버는 게임 콘텐츠를 위한 지도, NPC, AI 등 많은 데이터가 필요하며, 그로 인해 사용하는 메모리가 많습니다. 그래서 많은 메모리를 활용할 수 있도록 주로 64bit 아키텍처로 빌드합니다. 64bit 프로세스는 이론상 16 엑사 바이트 메모리를 사용할 수 있지만, 물리적으로는 아직 장비를 구성할 수 없습니다. ( 1테라바이트 램이라고 해도 수십만 개가 필요합니다.) OS별로 사용할 수 있는 메모리도 다르므로, 시스템에 맞게 매뉴얼을 찾아봐야 합니다.

메모리 사용량도 64bit 시스템에 걸맞게 상당합니다. 대략 2GB 이상 메타데이터를 로딩하며, 실제 유저가 유입하기 시작하면 기하급수적으로 증가합니다. 모 프로젝트를 예를 들면, A 프로젝트는 6000명 접속자 기준으로 55GB쯤 사용합니다. 하지만 사용 중인 리소스에서 유저 데이터가 차지하는 비용은 생각보다 작습니다. 대부분은 게임 세계를 구성하기 위한 데이터이며, 월드를 시뮬레이션하기 위한 비용입니다. NPC, AI, 지도 등이죠. 그래서 MMORPG 서버는 유저가 적게 유입하더라도 기본 메모리 사용량이 꽤 높다고 할 수 있습니다.

MMORPG 서버에 프로파일러를?

프로파일러를 MMORPG 서버에 붙여서 구동하면, 대부분 프로파일러는 서버 시작부터 연동해서 구동하며, 시작부터 여러분에게 좋지 않은 체험을 제공할 겁니다. 즉, 테스트 시작을 위한 준비까지 시간이 오래 걸립니다. 실제 서비스하는 규모만큼 유저가 유입되면 거의 월드가 정지될 것 같습니다.

그래도 메모리릭을 찾기 위해 툴의 도움은 받아야 하니 어떻게든 돌려봅시다. 풀 부하는 힘들고 한정적인 인원으로 테스트하면 겨우 가능할 것 같습니다. 제 경험상으로는 최대 부하 대비 1/50 ~ 1/100 정도 수준으로 줄여야, 겨우 테스트를 할 수 있었습니다. 높은 확률로 재현되는 메모리 이슈는 작은 단위 테스트로도 쉽게 재현할 수 있으니 프로파일러를 활용해 봅시다.

Visual Studio Diagnostic Tools

그래서 무엇을 사용하면 편리할까요? 윈도우 개발자라면 비주얼 스튜디오 프로페셔널(Visual Studio Professional)을 사용하실 것이므로, 비주얼 스튜디오 진단 도구를 추천합니다. 사용을 권장하는 제일 중요한 이유는 다른 프로파일러와는 달리, 프로세스 구동 중간에 프로파일러를 켤 수 있습니다. 즉, 테스트 준비 시간을 많이 줄일 수 있습니다. 이것만으로도 사용가치가 있다고 봅니다.

사용 방법

사용 방법은 심플합니다. 총 네 번만 클릭하면 분석 데이터를 만들 수 있습니다.

총 네 번 클릭해서 분석 데이터를 만들 수 있습니다.

해당 UI는 프로세스를 구동하면 제일 우측에 나타납니다. 먼저, 메모리 사용량 탭으로 이동합니다. 오른쪽 끝에 보이는 ‘힙 프로파일링’을 클릭해 활성화합니다. 스냅샷 만들기를 클릭 후, 시간차를 두고 다시 클릭해 두 대조군을 만들고, 마지막으로 힙 크기 열에 나타난 숫자를 클릭합니다. 어느 메모리가 증가했고, 감소했는지 분석한 결과를 볼 수 있습니다.

주의하실 사항은, 힙 프로파일링을 활성화한 상태에서는 비주얼 스튜디오 재시작이나, 다시 버튼을 누르지 않으면 계속 활성화 상태로 유지됩니다. 꼭 다시 눌러 비활성화해야 합니다. 또한, 비활성화했다 하더라도, 프로세스를 재시작해야 적용됩니다.

간편함

실제 사용해 보시면 간편하다고 느끼실 겁니다. 또한 다른 툴에 비해 성능 저하가 비교적 적습니다. 그렇다고 성능에 매우 적은 영향을 준다는 의미는 아니지만, 개발 중 테스트해 볼 수 있을 정도의 성능은 나오는 것 같습니다. 그리고 서버 구동부터가 아니라, 필요한 시점부터 프로파일러를 활성화 할 수 있다는 점도 매력적입니다. 시작부터 프로파일러로 인한 시간 부담을 없앨 수 있으니까요. 게다가 데이터 시각화도 아주 만족할 수준은 아니지만 깔끔하게 보여주는 편입니다. 

주의사항

리소스 사용량 제한 사용

이미 이 툴을 사용해 보신 분이 많을 겁니다. 하지만 만약 처음 사용하는 분이라면, 메모리를 일정 이상 사용할 때 프로파일러가 멋대로 종료되는 현상을 보실 수 있습니다. 이것 때문에 사용하기가 꺼려질 수도 있습니다. 이 현상은 프로파일러에 ‘리소스 사용량 제한 사용’이라는 기능이 있기 때문에 등장합니다. 

리소스 사용량 제한 사용 옵션을 비활성화해서 사용하기를 추천합니다.

리소스 사용량 제한 사용은 기본(Default)으로 활성화돼 있습니다. MMORPG같이 메모리를 많이 사용하는 프로젝트라면 이런 사용량 제한 조건으로는 오래 유지하기 힘드실 겁니다. 즉, 해당 기능을 비활성화하고 테스트를 한다면 비교적 만족스럽게 사용할 수 있습니다. 물론 이 기능을 비활성화해도 멋대로 종료되는 현상이 나타날 순 있습니다만, 상대적으로 오래 구동할 수 있으니 비활성화해서 사용하기를 추천합니다.

메모리릭을 판단하기 위한 힌트

우리가 원하는 최상의 결과는 정확한 메모리릭 부분입니다. 하지만, 메모리 프로파일러를 통해 얻는 결과는 우리가 원하는 결과가 아닐 수 있습니다. 메모리 프로파일러는 정확한 답을 제공해주지는 못합니다.

프로파일러가 작업자의 의도까지 파악할 수는 없기 때문에, 이것이 상주 데이터인지 릭인지 판단할 수 있는 기준을 알지 못합니다. 그래도 쓸모없지는 않습니다. 오래된 데이터 위주로 정렬해서 확인하거나, 점차 많은 영역을 차지하는 객체를 통해 우선 감별을 해볼 수 있습니다. 즉, 프로그램 의도를 정확히 알고 분석해야 최소한 범위를 줄일 수 있는 힌트를 얻을 수 있다는 의미입니다. 

프로파일러가 제공하는 힌트로 소스 코드 전체를 분석해야 하는 최악의 상황을 피할 수 있다는 것만으로도 충분히 가치가 있다고 할 수 있지 않을까요?

이번 글에서는 메모리릭의 의미와 비주얼 스튜디오 진단 도구를 활용해 메모리릭을 찾는 방법을 살펴봤습니다. 다음 글에서는 수동으로 메모리릭을 찾는 방법을 공유하겠습니다.