Linux에서는 Posix threading library에 포함되어 있는 PTMalloc2가 기본 메모리 관리자로 사용된다.
Linux의 malloc()나 free() 시스템 콜을 이용해서 메모리를 할당하고 해제한다 하더라도
항상 Linux system call이 호출되는 것이 아니라, PTMalloc2에서는 brk/sbrk/mmap 등을 통해서
큰 메모리 영역을 할당받아서 PTMalloc2 library가 요청된 메모리를 할당해주는 방식으로 처리된다.
Linux의 malloc()나 free() 시스템 콜을 이용해서 메모리를 할당하고 해제한다 하더라도
항상 Linux system call이 호출되는 것이 아니라, PTMalloc2에서는 brk/sbrk/mmap 등을 통해서
큰 메모리 영역을 할당받아서 PTMalloc2 library가 요청된 메모리를 할당해주는 방식으로 처리된다.
그런데, PTMalloc2은 아래와 같은 2가지 단점을 가지고 있다.
- Multithreading(over concurrent 32 ~ 64) model에서 성능 저하
- 고부하(잦은 malloc와 free) 시스템에서 메모리 조각화로 인한 재사용 불가
- 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이 준비되어 있다.
첫번째 단점때문에, 이를 보완하기 위해서 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에서 나타났던 현상으로, 실제 이런 조각화로 인해서 재사용되지 못하는 메모리 공간이 상당할 것으로 예측된다.
실제 소프트웨어에서 메모리를 할당해서 사용후 운영체제로 반납은 하지만, 너무 조각화되어 있어서 mmap에서 그 메모리를 다른 용도로 재활용하지 못해서
메모리 릭과 같은 현상들이 발생하기도 한다.
kakao의 Story DB에서 나타났던 현상으로, 실제 이런 조각화로 인해서 재사용되지 못하는 메모리 공간이 상당할 것으로 예측된다.
각각 JEMalloc와 PTMalloc2 Memory Allocator를 사용하는 MySQL 서버에 동일한 부하를 하루 정도 가하여
MySQL 서버에서 사용하는 메모리 사용량을 조사해 본 결과는 첨부된 파일과 같다.
두 서버 모두 32GB의 물리적 메모리를 장착하고 있으며, InnoDB Buffer Pool을 20GB로 설정하였다.
MySQL 서버에서 사용하는 메모리 사용량을 조사해 본 결과는 첨부된 파일과 같다.
두 서버 모두 32GB의 물리적 메모리를 장착하고 있으며, InnoDB Buffer Pool을 20GB로 설정하였다.
이틀정도의 테스트 결과, PTMalloc는 33.00GB 정도의 메모리를 사용했고,JEMalloc는 30.15GB의 메모리를 사용했다.
대략 JEMalloc가 2.85GB 정도의 메모리를 덜 사용했으며, 결과적으로 스왑 사용 시점도 PTMalloc보다는 늦게 발생했다.
대략 JEMalloc가 2.85GB 정도의 메모리를 덜 사용했으며, 결과적으로 스왑 사용 시점도 PTMalloc보다는 늦게 발생했다.
참고 사이트
http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage/
http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage-continued/
http://mikaelronstrom.blogspot.com/2010/11/king-is-dead-long-live-king.html
http://bugs.mysql.com/bug.php?id=57480
http://goog-perftools.sourceforge.net/doc/tcmalloc.html
http://www.canonware.com/jemalloc/
http://www.facebook.com/notes/facebook-engineering/scalable-memory-allocation-using-jemalloc/480222803919
http://blogs.innodb.com/wp/2011/12/improving-innodb-memory-usage-continued/
http://mikaelronstrom.blogspot.com/2010/11/king-is-dead-long-live-king.html
http://bugs.mysql.com/bug.php?id=57480
http://goog-perftools.sourceforge.net/doc/tcmalloc.html
http://www.canonware.com/jemalloc/
http://www.facebook.com/notes/facebook-engineering/scalable-memory-allocation-using-jemalloc/480222803919