2013년 9월 23일 월요일

JEMalloc vs PTMalloc2

Linux에서는 Posix threading library에 포함되어 있는 PTMalloc2가 기본 메모리 관리자로 사용된다.
Linux의 malloc()나 free() 시스템 콜을 이용해서 메모리를 할당하고 해제한다 하더라도
항상 Linux system call이 호출되는 것이 아니라, PTMalloc2에서는 brk/sbrk/mmap 등을 통해서
큰 메모리 영역을 할당받아서 PTMalloc2 library가 요청된 메모리를 할당해주는 방식으로 처리된다.
그런데, PTMalloc2은 아래와 같은 2가지 단점을 가지고 있다.
- Multithreading(over concurrent 32 ~ 64) model에서 성능 저하
- 고부하(잦은 malloc와 free) 시스템에서 메모리 조각화로 인한 재사용 불가
아주 빈번히 작은 공간의 메모리를 할당받고 해제해야 하는 MySQL 서버에서는 PTMalloc2의
첫번째 단점때문에, 이를 보완하기 위해서 Google에서 개발된 TCMalloc나 JEMalloc를 많이들 검토하고 적용하고 있다.
- TCMalloc : Google에서 개발된 Thread Cache 기반의 메모리 할당 라이브러리로써, Chrome이나 Google 내부 시스템에서 사용중
- JEMalloc : FreeBSD의 기본 Memory Allocator를 Linux용으로 포팅한 것이며, TCMalloc와 같이 Thread cache 기반의 Memory Allocator로 Facebook에서 지원하고 내부적으로 사용하고 있다. 또한 Linux용 Redis도 기본적으로는 JEMalloc를 사용하여 빌드되도록 Makefile이 준비되어 있다.
그런데, MySQL이나 Redis와 같이 메모리 사용이 빈번한 소프트웨어에서 PTMalloc2는 메모리 릭과 같은 현상들을 유발하기도 하는데,
실제 소프트웨어에서 메모리를 할당해서 사용후 운영체제로 반납은 하지만, 너무 조각화되어 있어서 mmap에서 그 메모리를 다른 용도로 재활용하지 못해서
메모리 릭과 같은 현상들이 발생하기도 한다.
kakao의 Story DB에서 나타났던 현상으로, 실제 이런 조각화로 인해서 재사용되지 못하는 메모리 공간이 상당할 것으로 예측된다.
각각 JEMalloc와 PTMalloc2 Memory Allocator를 사용하는 MySQL 서버에 동일한 부하를 하루 정도 가하여
MySQL 서버에서 사용하는 메모리 사용량을 조사해 본 결과는 첨부된 파일과 같다.
두 서버 모두 32GB의 물리적 메모리를 장착하고 있으며, InnoDB Buffer Pool을 20GB로 설정하였다.
이틀정도의 테스트 결과, PTMalloc는 33.00GB 정도의 메모리를 사용했고,JEMalloc는 30.15GB의 메모리를 사용했다.
대략 JEMalloc가 2.85GB 정도의 메모리를 덜 사용했으며, 결과적으로 스왑 사용 시점도 PTMalloc보다는 늦게 발생했다.


참고 사이트


댓글 3개:

  1. 안녕하세요.
    CDNetworks에 근무하는 박수현 이라고 합니다.

    동일한 부하를 MySQL에 주셨다면 메모리 사용량 외에 DB의 성능적인 면에서의 결과도 같이 공유해 주실 수는 없나요?

    답글삭제
  2. 위의 테스트는 성능적인 문제를 염두해 두고 테스트한 것이 아니고 서비스내의 문제점을 해결하고자 위 function의 memory 사용량에 대한 차이점 검토를 주 목적으로 한 테스트였기 때문에 성능 데이터를 공유하여도 테스트 환경과 동일한 transaction이 아닌 이상 큰 도움이 되지 못 할 것으로 판단됩니다.
    mysql 성능은 해당 서비스 성격에 따라 영향을 받기 때문에 위의 서버 spec의 경우 초당 30,000 QPS를 받는 경우도 있고 초당 5,000이상은 불가능 한 경우도 있습니다.(data in innodb buffer의 경우)
    * CPU 사용률 40% under, load 5~6 이하를 기준할 경우

    답글삭제
  3. 안녕하세요 다우기술이라는 회사에 근무하는 김성래 입니다.

    저희도 C 데몬 프로세스들이 이상하게 메모리를 많이 사용하는 현상이 보여 이를 개선하려 하던도중에 이 글을 보았습니다.

    소개해주신 JEMalloc/TCMalloc 2가지의 솔루션이 있던데, 저희는 최종적으로 TCMalloc을 사용 하였네요.

    결과는 메모리 사용량이 2GB까지 RES가 상승 하던 상황에서 380MB에서 더이상 늘지 않게 되었네요.

    특이한점은 C++의 STL과 같이 내부적으로 new/delete가 자주 일어나는 컨테이너를 많이 사용한 프로세스 일 수록 메모리 사용량 개선이 많이 되었는데..

    언급하신대로.. 메모리 조각화에 의한 현상이 아닌가 생각합니다.

    TCMalloc/JEMalloc 단순히 속도 이슈때문에 사용하는것이라고 생각했었는데, 이런 장점도 있었네요.

    답글삭제