2011년 11월 13일 일요일

TCMalloc

Chromium의 소스 분석을 시작하면서 다음의 코드를 만나게 되었습니다.

//src/content/app/content_main.cc
tc_set_new_mode(1);

이 함수는 tcmalloc 에서 제공하는 API 입니다.

흐음... tcmalloc은 뭘까요?
tcmalloc 은 Thread-Caching Malloc의 약자로 구글성능도구(google-perftools) 패키지에 포함되어 있습니다.

이름에서 알수있는 것처럼 thread 별로 malloc 관리를 하는 라이브러리인데요,
doc page 를 읽어보면 각각의 쓰레드에 thread-local cache를 배정한다고 나와있습니다. (TCMalloc assigns each thread a thread-local cache.)

쓰레드에서 malloc 이나 new 를 통해 메모리 할당을 요청하면, thread-local cache에서 메모리할당이 수행되는 것인데요, 왜 이런 과정이 필요하게 된걸까요?
쓰레드를 많이 사용하는 프로그램에서는 기존 메모리 할당 방법(glibc malloc)으로는 어떤 문제가 있길래 쓰레드단위로 메모리 할당이 이루어지도록 했는지 궁금하네요.

많은 쓰레드가 동작하는 상황에서 기존 malloc 사용시 다음 문제가 생기는 것 같습니다.
아래 글은 다음 블로그에서 참고하였습니다 (http://lethean.pe.kr/2009/04/29/tcmalloc-google-perftools/)

장기간 실행되면서 빈번하게 메모리를 할당 / 해제하는 것은 물론 수십 개의 쓰레드가 동작하는 프로그램에서는 어쩔 수 없이 메모리 단편화(Memory Fragmentation)가 발생합니다. 메모리 단편화가 많을 경우 어플리케이션 로직에 메모리 누수(memork leak)가 없어도 C 라이브러리 메모리 관리자가 메모리를 커널에 반환하지 않기 때문에 프로세스의 메모리 사용량은 계속 늘어납니다.(참고로 이러한 경우인지 여부는 주기적으로mallinfo() 정보를 확인하면 됩니다) 물론 이를 회피하기 위한 기법이나 아키텍쳐는 많이 있지만, 그리 쉽게 원하는 성능과 효율을 얻기는 힘들더군요. "


여러 쓰레드에서 메모리 할당/해제를 하게되면 glibc 내 malloc이 관리하는 메모리 풀의 단편화가 심해져서 커널에 메모리 반환이 잘 안되는 모양입니다. 그래서 쓰레드가 종료가 되더라도 메모리 단편화로 인해 glibc는 종료된 쓰레드가 사용했던 메모리 반환을 못하게되어 메모리 사용량이 줄지않고 계속 늘어나는 현상이 생길 수 있겠습니다.

tcmalloc 을 사용하면 malloc에 비해 빠르고 효율이 좋다고 합니다. 성능은 할당/해제 시간일 테고, 효율은 오래 프로그램을 돌리더라도 메모리 사용량이 잘 관리가 되는 것이겠네요.

사용해보지는 않았지만, 이제 앞으로는 tcmalloc을 이용하여 개발을 해야겠습니다. ^^

마지막으로, tcmalloc을 알게 해준 tc_set_new_mode() 함수에 대해 간단히 정리를 하고 넘어가야겠습니다.
이 함수의 주석은 다음과 같습니다.

" This function behaves similarly to MVSC's _set_new_mode.
   If flag is 0 (default), calls to malloc will behave normally.
   If flag is 1, calls to malloc will behave like calls to new,
   and the std_new_handler will be invoked on failure. "

아~ tc_set_new_mode(1)은 메모리 할당 실패 시, std_new_hander에 정의된 핸들러를 호출하라고 지시하는 함수네요.

근데,,, glibc, tcmalloc 모두 링크되는데 프로그램은 실행시 어떻게 tcmalloc의 malloc을 사용할까요???

댓글 없음:

댓글 쓰기