MySQL5.5でtcmallocを使用する

tcmallocについて

Googleのgperftoolsに含まれるmallocライブラリ。一時MySQLで使うと速くなるよ、といった話題が出てた割に5.5系のMySQLで使う方法についてあんまり見かけないので書いてみる。

インストール環境

今回書いている環境は以下のようになります。

libunwindのインストール

まずはgperftoolsのコンパイルに必要なlibunwindをインストールします。

# wget http://download.savannah.gnu.org/releases/libunwind/libunwind-1.1.tar.gz
# tar zxf libunwind-1.1.tar.gz 
# cd libunwind-1.1
# ls
acinclude.m4  AUTHORS         aux        config     configure.ac  doc      INSTALL  Makefile.am  NEWS    scripts  tests
aclocal.m4    autom4te.cache  ChangeLog  configure  COPYING       include  LICENSE  Makefile.in  README  src      TODO
# ./configure
# make
# make install
# ldconfig
# ldconfig -p | grep wind
	libunwind.so.8 (libc6,x86-64) => /usr/local/lib/libunwind.so.8
	libunwind.so (libc6,x86-64) => /usr/local/lib/libunwind.so
	libunwind-x86_64.so.8 (libc6,x86-64) => /usr/local/lib/libunwind-x86_64.so.8
	libunwind-x86_64.so (libc6,x86-64) => /usr/local/lib/libunwind-x86_64.so
	libunwind-setjmp.so.0 (libc6,x86-64) => /usr/local/lib/libunwind-setjmp.so.0
	libunwind-setjmp.so (libc6,x86-64) => /usr/local/lib/libunwind-setjmp.so
	libunwind-ptrace.so.0 (libc6,x86-64) => /usr/local/lib/libunwind-ptrace.so.0
	libunwind-ptrace.so (libc6,x86-64) => /usr/local/lib/libunwind-ptrace.so
	libunwind-coredump.so.0 (libc6,x86-64) => /usr/local/lib/libunwind-coredump.so.0
	libunwind-coredump.so (libc6,x86-64) => /usr/local/lib/libunwind-coredump.so
#

gperftoolsのインストール

準備が出来た所でtcmallocが含まれるgperftoolsをインストールします。

# wget https://gperftools.googlecode.com/files/gperftools-2.0.tar.gz
# tar zxf gperftools-2.0.tar.gz
# cd gperftools-2.0
# ls
aclocal.m4  compile       configure     depcomp         INSTALL     ltmain.sh    Makefile.in    NEWS      README_windows.txt  vsprojects
AUTHORS     config.guess  configure.ac  doc             install-sh  m4           missing        packages  src
ChangeLog   config.sub    COPYING       gperftools.sln  libtool     Makefile.am  mkinstalldirs  README    TODO
# 
# ./configure
# make
# make install
# ldconfig
# ldconfig -p | grep tcmalloc
	libtcmalloc_minimal_debug.so.4 (libc6,x86-64) => /usr/local/lib/libtcmalloc_minimal_debug.so.4
	libtcmalloc_minimal_debug.so (libc6,x86-64) => /usr/local/lib/libtcmalloc_minimal_debug.so
	libtcmalloc_minimal.so.4 (libc6,x86-64) => /usr/local/lib/libtcmalloc_minimal.so.4
	libtcmalloc_minimal.so (libc6,x86-64) => /usr/local/lib/libtcmalloc_minimal.so
	libtcmalloc_debug.so.4 (libc6,x86-64) => /usr/local/lib/libtcmalloc_debug.so.4
	libtcmalloc_debug.so (libc6,x86-64) => /usr/local/lib/libtcmalloc_debug.so
	libtcmalloc_and_profiler.so.4 (libc6,x86-64) => /usr/local/lib/libtcmalloc_and_profiler.so.4
	libtcmalloc_and_profiler.so (libc6,x86-64) => /usr/local/lib/libtcmalloc_and_profiler.so
	libtcmalloc.so.4 (libc6,x86-64) => /usr/local/lib/libtcmalloc.so.4
	libtcmalloc.so (libc6,x86-64) => /usr/local/lib/libtcmalloc.so
#
# ldd /usr/local/lib/libtcmalloc.so
	linux-vdso.so.1 =>  (0x00007fffd6fff000)
	libunwind.so.8 => /usr/local/lib/libunwind.so.8 (0x00007f51f5209000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f51f4fec000)
	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f51f4ce5000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f51f4a61000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f51f46ce000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003edb800000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f51f44b7000)
#

以上で準備完了です。

MySQLでtcmallocをロードして起動

MySQL5.5ではmy.cnfの[mysqld_safe]セクションに以下のように記載して起動することでtcmallocを使用することが出来ます。この辺りは最初の方に書いたMySQL公式サイトに記載されています。

# grep -A1 mysqld_safe my.cnf 
[mysqld_safe]
malloc-lib=/usr/local/lib/libtcmalloc_minimal.so
# /usr/local/mysql/bin/mysqld_safe &
[1] 18914
# 130124 01:21:50 mysqld_safe Adding '/usr/local/lib/libtcmalloc_minimal.so' to LD_PRELOAD for mysqld
130124 01:21:50 mysqld_safe Logging to '/usr/local/mysql/data/mysqld.err'.
130124 01:21:50 mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/data

#
# cat /proc/`cat /usr/local/mysql/data/*.pid`/smaps | grep tcma
7fcb87a8f000-7fcb87ab5000 r-xp 00000000 fc:02 289021                     /usr/local/lib/libtcmalloc_minimal.so.4.1.0
7fcb87ab5000-7fcb87cb5000 ---p 00026000 fc:02 289021                     /usr/local/lib/libtcmalloc_minimal.so.4.1.0
7fcb87cb5000-7fcb87cb7000 rw-p 00026000 fc:02 289021                     /usr/local/lib/libtcmalloc_minimal.so.4.1.0
#

またはソースからビルドしてMySQLを入れる場合は以下のようにcmakeのオプションで指定することで最初からtcmallocをmysqldにリンクすることも可能です。

# cmake \
  -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-tc \
  -DWITH_MYSQLD_LDFLAGS=-ltcmalloc \
  -DENABLED_LOCAL_INFILE=1 \
  -DMYSQL_TCP_PORT=3306 \
  -DMYSQL_UNIX_ADDR=/tmp/mysql-tc.sock \
  -DWITH_EXTRA_CHARSETS=all \
  -DWITH_READLINE=1
# make
# make install
#
# ldd /usr/local/mysql-tc/bin/mysqld
        linux-vdso.so.1 =>  (0x00007fffb9780000)
        libtcmalloc.so.0 => /usr/local/lib/libtcmalloc.so.0 (0x00007f2bf44fe000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x000000363f400000)
        librt.so.1 => /lib64/librt.so.1 (0x000000363fc00000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x0000003641400000)
        libdl.so.2 => /lib64/libdl.so.2 (0x000000363ec00000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003641c00000)
        libm.so.6 => /lib64/libm.so.6 (0x000000363f800000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003640c00000)
        libc.so.6 => /lib64/libc.so.6 (0x000000363f000000)
        libunwind.so.8 => /usr/local/lib/libunwind.so.8 (0x00007f2bf42e2000)
        /lib64/ld-linux-x86-64.so.2 (0x000000363e800000)
        libfreebl3.so => /lib64/libfreebl3.so (0x0000003641800000)
#

この例だとminimalじゃないけどDWITH_MYSQLD_LDFLAGSで指定するものを変更すればminimalに出来ると思います。こちらはまだ実際に試した事無いです。

終わりに

MySQL5.5だとこんな感じでtcmallocを使用するように出来ます。以前通常コンパイルMySQLと後述のcmake時点で組み込む形でtcmallocを使用するようにしたMySQL、両方5.5系、ではベンチマーク(sysbench)を行った際にtcmallocの方が同時接続数が増えた際の性能の落ち込みが少なかったです。またほとんどのケースでtcmallocの方がtransaction/secは高い値となりました。
先日の日記で書いたSSDベンチマークを取る際もtcmallocの使用有無でどの程度差が出るか検証してみたいと思います。