kth 개발자 블로그

개발자가 행복한 회사 kth

 

마지막 남은 공짜 점심. Facebook의 메모리 할당자 jemalloc

May 12, 2011

by KTH 기술연구소 분산기술랩 하용호

 

바쁘신 분들을 위한 핵심 요약

Facebook이 소개한 jemalloc은 Google의 tcmalloc과 함께 요즘에 뜨는 메모리 할당자 ( malloc ) 입니다. 둘 다 기존 바이너리를 고치지 않고, 실행 전 한 줄 추가하는 것만으로 수십 퍼센트의 성능향상을 얻을 수가 있습니다. 꼭 테스트하고 사용해보도록 합시다.

 

소개

연초에 Facebook에서 Jason Evans씨가 쓴 “Facebook은 메모리 할당자를 jemalloc을 써서 속도향상을 얻었다”는 글이 개발자들의 트위터 타임라인을 한창 돌아다녔습니다. 무엇을 하든 화제가 되는 기업이 Google에서 Facebook으로 넘어간 듯한 느낌이었습니다. 이들이 쓰는 jemalloc은 어떤 것일까요?

 

Malloc

프로그램이 무엇을 하려 하든, 시스템에서 메모리를 받아오는 일이 가장 먼저입니다. 도화지가 있어야 그림을 그릴 수 있으니까요. 때문에 메모리를 할당 받는 malloc은 C, C++ 프로그래머들이 가장 많이 사용하는 call 입니다. 효율적인 malloc을 만들고자 하는 대가들의 도전은 지금도 계속되고 있습니다. 프로그램이 도는 동안 수십, 수백만 번 이상 불리기에, 소스를 고치지 않고 빠른 malloc을 사용하는 것만으로 전체 프로그램의 속도가 올라가기 때문이죠.

 

Malloc의 중요성에 대한 재조명

malloc은 원래부터 중요했습니다만, 최근의 멀티코어, 멀티스레드 환경에서 동작하는 서버 프로그램에서 다음 측면 때문에 더욱 중요해지고 있습니다.

속도 – 최근에는 프로그램 하나가 많은 수의 스레드를 사용하고, 각 스레드가 여러 CPU에 분산되어 실행되게 되었습니다. 이 상황에서도 메모리를 효율적으로 분배하는 일은 그렇게 쉬운 일이 아닙니다. 많은 스레드를 다루게 되면 기존 malloc library의 성능이 주저 앉기 시작합니다. 예를 들어 리눅스에 기본으로 들어있는 glibc malloc의 경우 스레드 8개 이상을 돌리기 시작하면 최고 성능의 60% 수준으로 떨어져 버립니다. 당연히 그것을 쓰는 프로그램도 성능이 뚝 낮아져버리는 겁니다. 대책이 필요합니다.

공간 효율성 – malloc은 도화지에서 그림을 그리기 위한 구역을 따오는 것과 비슷합니다. 도화지에서 중구난방으로 영역을 가져오면, 여기저기에 구멍이 숭숭 뚫리게 됩니다. 이렇게 오랜 시간 동안 쓰게 되면, 전체 도화지에서 아직 칠할 수 있는 전체 면적은 많지만, 단일 덩어리로서의 큰 여백이 점차 사라져서, 있어도 못쓰는 현상이 발생합니다(fragmentation). 오랜 시간 동작하는 서버 프로그램에서 이 부분은 특히나 치명적입니다. 메모리가 충분히 남아 있는데도, 메모리 공간이 부족하다가 시스템이 죽는 현상을 겪어보셨을 텐데 바로 이 경우에 해당합니다. 따라서 오랜 시간 영역을 할당 받고 해제하더라도 큰 면적을 잘 보존하는 malloc이 더욱 중요해졌습니다.

사실 속도와 공간 효율성은 두 마리의 토끼와 같아 동시에 달성하기 어렵습니다만, 소프트웨어 엔지니어들의 각고의 노력 끝에 둘 다 쫓을 수 있는 malloc이 점차 나오고 있습니다. 오늘 소개드릴 jemalloc이 바로 그 예입니다.

 

대표적인 malloc 들

jemalloc은 하늘에서 뚝 떨어진 것이 아닙니다. 기존의 malloc개발 역사 계보를 따라 가고 있습니다. 아주 과거의 역사를 제외하면, 최근에 가장 많이 쓰이는 malloc들은 다음과 같은 것들이 있습니다.

dlmalloc – Doug Lea 아저씨가 만들었던 malloc입니다. 빠르지는 않고, 예전에 만들어져서 멀티코어, 멀티스레드 개념도 고려되지 않았습니다. 그러나 이후 많은 malloc의 베이스가 됩니다. 참고로 doug Lea 씨는 Java Concurrency의 대가 입니다. 이분이 2006년에 쓰신 Java Concurrency in Practice 는 자바로 서버 쪽 프로그래밍 하시는 분들에게는 아직도 매우 강력히 추천되는 서적입니다. (우리나라에도 번역서가 나와있습니다.)

ptmalloc – glibc에 포함된 malloc입니다. 리눅스의 사실상 표준이란 이야기죠. dlmalloc기반에 멀티코어와 멀티스레드 개념이 고려되었습니다. 뒤에 설명드릴 jemalloc의 arena 개념도 ptmalloc2에 먼저 도입되어 있습니다. 제일 빠른 malloc은 아니지만, 범용적인 사용에 평균적인 성능을 보여주기에 아직까지 리눅스 glibc 기본으로 채택되어 있습니다. 고지식한 모범생 같은 녀석입니다.

tcmalloc – 구글의 Sanjay Ghemawat 아저씨가 만든 malloc입니다. “구글이 만들면 malloc도 다릅니다.”를 천명하며 많은 이들을 열광시킨 malloc입니다. 이름부터 thread caching malloc으로 thread에 대한 고려가 매우 크게 되었고, ptmalloc대비 굉장히 빠릅니다. 덤으로 이 malloc을 쓰면 구글의 여러가지 프로그램 분석도구, 튜닝도구들이 제공 됩니다. 이들이 매우 훌륭합니다. 참고로 이 아저씨가 Google File System도 만들고 MapReduce, BigTable 도 만들었습니다. 구글의 인프라를 만든 사람입니다. 사람보다는 괴물에 가깝습니다.

 

그럼 이제 정말 jemalloc을 살펴봅시다.

올 초에 “Facebook에서 쓴다!” 해서 유명해진 jemalloc이지만, 사실 malloc계에서는 (이런 계가 정말 있는지는 모르겠습니다만) 이미 이전부터 유명한 malloc입니다. 올 초에 더 유명해지긴 했지만, jemalloc을 만든 Jason Evans 씨는 FreeBSD 운영체제 진영의 유명한 개발자였습니다. 이 분이 2006년에 낮은 malloc성능으로 고생하던 FreeBSD를 위해 만든 malloc이 jemalloc입니다. 2007년부터 FreeBSD 표준으로 도입되었습니다. 참고로 소프트웨어 기술 혁신은 전통적으로 FreeBSD쪽 진영에서 많이 나왔습니다. FreeBSD에서 선구적으로 시작되었던 것들이 후에 Linux에 많이 도입되곤 합니다.

현재 jemalloc은 여러분이 많이 쓰는 Firefox에도 사용되고 있습니다. Firefox2에서 메모리 단편화 문제가 계속 발생하자 firefox3에서 적용되었습니다. 참고로 safari, chrome등에서는 Google의 tcmalloc을 사용하고 있습니다.

 

jemalloc의 기술적 특성

jemalloc은 이전의 malloc들에서 시도되고 검증되었던 많은 기술들이 모여 있습니다. 자잘한 부분보다 아키텍처 적으로 가장 눈에 띄는 부분을 꼽자면 역시 arena와 thread cache입니다. (사실 이 두가지는 tcmalloc의 아키텍처와도 거의 같습니다. jemalloc만의 독특한 부분들에 대해서는 별도의 포스팅으로 한번 더 알아보겠습니다.)

Arena

최근의 malloc들은 메모리를 통짜로 관리하기 보다는 그보다는 작은 덩어리 여러 개로 나누어서 관리합니다. 그리고 각 스레드에게 덩어리들을 할당해 주는 거지요. 이 덩어리를 arena라 부릅니다. 아이들 여러 명에게 도화지 하나를 주고, 각자 원하는 위치에 점을 찍으라고 시키는 것을 상상해 봅시다. 통짜 도화지라면, 너는 여기 찍고 나는 여기 찍고 서로 눈치를 보면서(Synchronization) 찍어야 할겁니다. 하지만 선생님이 미리 도화지에 금을 그어 주면, 자기 영역에서 눈치 안보고 신나게 빠른 속도로 점을 찍을 수 있겠죠. 이런 개념이 바로 arena 입니다.

Thread cache

작은 단위의 잦은 메모리 할당의 경우, arena를 참조 하지 않고, 바로 malloc을 할 수 있도록, 각 스레드에게 thread cache라는 영역을 줍니다. 이 아이디어는 Google의 tcmalloc의 핵심 부분인데 jemalloc에도 구현되어 있습니다.

아까 그 아이들을 다시 떠올려 봅시다. 이번에는 공통의 도화지에 추가로, 아이들 각자에게 A4용지를 한 장씩 나눠줍니다. 그러면 아이들은 작은 점을 찍을 경우, 도화지까지 달려가서 자기 영역을 찾을 동작을 할 필요가 없습니다. (No Arena Seeking). 자기 손의 종이에 잽싸게 점을 찍었다 지웠다 할 수 있습니다(Using Thread Cache) 남들 눈치 전혀 안보고 (No Synchronization, No Locking) 엄청나게 빠른 속도로 말입니다.

아래 그림은 jemalloc 구조의 핵심 layout입니다. 뭔가 복잡해 보이지만 위에서 설명한 것들이 대부분입니다.

jemalloc architecture

 

실제 jemalloc의 성능은?


맨 왼쪽에 있는 것이 glibc의 malloc입니다. 그리고 맨 오른쪽에 있는 것이 jemalloc의 성능이죠. 기본 대비 거의 두 배가 넘게 성능이 좋습니다. 아주 압도적인 성능차이죠. 이것을 쓴 서버 프로그램이 굉장히 빨라질 것은 자명한 현실입니다. 바로 옆에 tcmalloc은 jemalloc과 거의 비슷한 성능을 보이고 있습니다. 역시 Google도 만만하지 않습니다. tcmalloc의 성능은 jemalloc 2.1.0보다 4.5% 느립니다. 다만 비교된 tcmalloc의 버전이 1.4인데, 현재 tcmalloc의 최신 버전은 1.6이고, 이것이 1.4 보다 좀 더 좋았던 것을 생각하면, 실제 최신 버전의 두 malloc간의 성능 차이는 거의 없을 것으로 생각됩니다. jemalloc의 개발자인 Jason Evans도 이를 의식했는지 ‘비슷해 보이지만 CPU core가 8개가 넘는 서버 컴퓨터에서는 jemalloc이 더 빠르다’ 라고 했습니다. 다만 보통의 실 서버들은 딱 코어가 8개가 많은 지라(Quad * 2), 아직은 큰 이득을 보기가 어렵겠군요.

 

프로그래머들에게 남은 마지막 공짜 점심 – kth 분산 기술 Lab의 사례

공짜점심의 시대는 끝났다” 라는 글이 2005년에 발표되었습니다. 이전엔 프로그래머들이 가만히 있어도 CPU의 클럭 속도가 올라가면서 가만히 있어도 성능이 향상되었습니다. 하지만 이제 CPU는 클럭속도가 올라가기 보다, core의 개수가 늘어나는 식으로 발전하고 있고, 프로그래머들은 이러한 멀티 프로세서, 멀티 스레드 환경을 숙지하고, 거기에 맞게 완전히 다른 패러다임으로 프로그래밍을 해야 한다는 이야기였습니다.

6년이 지난 지금 그 이야기는 완전한 현실이 되었습니다. 사실상 CPU의 속도는 3Ghz대에서 멈추었고, 개수만 늘어나고 있습니다. 이제 프로그래머들은 멀티스레딩, 분산처리에 익숙해져야 빠른 속도를 얻을 수 있습니다. 하지만 아시다시피 이러한 프로그래밍은 “어렵습니다”. 그것도 아주 많이.

낑낑대며, 멀티스레드 코드를 튜닝 하는 프로그래머에게 주어진 마지막 공짜 점심이 바로, tcmalloc, jemalloc과 같은 malloc library입니다. 이들을 사용하는 데에는 코드를 수정할 필요도 없습니다. 특히 스레드를 많이 쓰는 프로그램과 어울릴 경우 수십% 수준의 성능 향상을 공짜로 얻을 수 있습니다.

제 경험을 공유해봅니다. 저는 kth 기술연구소 분산기술Lab에서 iLock이라는 ‘분산 동기화 도구’를 만들고 있습니다. (쉽게 설명하면, 분산환경에서의 동기화를 위해 쓰는 윈도우 레지스트리 같은 녀석입니다. 좀 더 기술적으로 보고 싶으신 분은 Google의 Chubby를 참고하세요.)  iLock에 Google의 tcmalloc을 적용한 결과, 앉은 자리에서 18~22%의 성능 향상을 얻었습니다. (적용에 걸린 시간은 겨우 몇 초!)

무엇보다 가장 큰 장점은 이것을 적용해 보기 위해, 복잡한 작업이 전혀 필요 없다는 것입니다. 소스를 재 컴파일 할 필요도 없습니다. 기존에 있는 바이너리를 실행하기 전에 커맨드 라인에서

$ LD_PRELOAD=”tcmalloc이 설치된 폴더/libtcmalloc.so”

을 지정해주기만 하면 됩니다. 그러면 이후 실행된 프로그램은 glibc표준 malloc(ptmalloc)대신 tcmalloc 또는 jemalloc 등을 쓸 수 있습니다. 이것만 해주면 성능 20% 향상이라니! tcmalloc, jemalloc등은 우리에게 남은 마지막 공짜 점심과 같은 녀석들입니다.

현재 분산기술 Lab에서는 jemalloc보다는 Google의 tcmalloc을 사용하고 있습니다. 이유는 둘간의 성능 차이가 거의 없지만, tcmalloc의 경우 Google에서 제공하는 다양한 프로그램 분석툴 (Heap profiler, Cpu profiler)등이 제공되고 있고, 이들이 performance critical한 프로그램을 개발하는데 큰 도움이 되기 때문입니다. 아마 처음 이런 새로운 malloc을 써보시려는 분들도 관련 문서와 지식을 얻기에는 tcmalloc쪽이 더 편리하실 것입니다.

 

그래야만 하는가? 그래야만 한다!

(베토벤의 현악 사중주 마지막 악장 악보에서)

최신의 malloc을 써야 하나요? 네. 써야 합니다! 만족하실 겁니다.

About the author

Yongho '하용호' 라고 합니다. kth 기술연구소 분산기술랩에서 즐겁게 일하고 있습니다. '프리즘 파일 시스템'이라는 분산파일 시스템, 'iLock'이라 이름 붙인 분산 동기화 서비스, 그리고 새로운 검색엔진을 만들고 있습니다. 분산처리, 데이터마이닝을 연구해 왔습니다. 대량의 자료를 다루는 것을 좋아합니다. Data Scientist를 지향합니다.

작성일 : 2011/05/12 | 태그: , , , , , ,
글 분류 퀵 리뷰 | 작성자 하용호 ( Yongho )

| Trackback URL


"마지막 남은 공짜 점심. Facebook의 메모리 할당자 jemalloc" 의 관련글 1 개

  1. MySQL5.5 with tcmalloc 성능 벤치마크 | 파란 개발자 블로그 wrote:

    [...] 직접 처리한다고 하네요. malloc 에 관한 자세한 내용은 하용호님의 글  “마지막 남은 공짜 점심. Facebook의 메모리 할당자 jemalloc” 를 읽어보시기 [...]

 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org