Ruby でスレッドを1000個ほど作るとプロセスサイズが 4GB ほどになります。
% ruby -e 'system "ps -o vsz -p #$$"; 1000.times{Thread.new{sleep}}; system "ps -o vsz -p #$$"' VSZ 46392 VSZ 4151572
jemalloc 使うと 2.5GB くらいになります。jemalloc すばらしい。
% LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 'system "ps -o vsz -p #$$"; 1000.times{Thread.new{sleep}}; system "ps -o vsz -p #$$"' VSZ 55672 VSZ 2509080
ところが jemalloc を使ったほうが時間がかかります。
% time ruby -e '1000.times{Thread.new{sleep}}' ruby -e '1000.times{Thread.new{sleep}}' 0.10s user 0.06s system 115% cpu 0.132 total
% time LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e '1000.times{Thread.new{sleep}}' LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 0.23s user 0.81s system 109% cpu 0.941 total
jemalloc を使わない場合は 0.13秒ですが、jemalloc を使うと 0.94秒かかってます。
プロセスサイズではなく OS の使用メモリを見てみます。
% ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; system "free"' total used free shared buffers cached Mem: 8056184 7719868 336316 97356 587492 5373632 -/+ buffers/cache: 1758744 6297440 Swap: 4194300 2800 4191500 total used free shared buffers cached Mem: 8056184 7766988 289196 97356 587492 5373632 -/+ buffers/cache: 1805864 6250320 Swap: 4194300 2800 4191500
jemalloc を使わない場合は、プロセスサイズは 4GB くらいでしたが、実際に使われているメモリは 47MB くらいです (前後 の used の差分)。
% LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; system "free"' total used free shared buffers cached Mem: 8056184 7721732 334452 89052 587520 5365352 -/+ buffers/cache: 1768860 6287324 Swap: 4194300 2800 4191500 total used free shared buffers cached Mem: 8056184 7780264 275920 87260 587520 5363568 -/+ buffers/cache: 1829176 6227008 Swap: 4194300 2800 4191500
jemalloc を使った場合は 60MB くらいで、逆に多く使用してしまっています。
さらに 10個ほど fork してみます。
% ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; 10.times{fork{sleep}}; sleep 1; system "free"' total used free shared buffers cached Mem: 8056184 2053828 6002356 68744 372796 613836 -/+ buffers/cache: 1067196 6988988 Swap: 4194300 0 4194300 total used free shared buffers cached Mem: 8056184 2246508 5809676 68744 372804 613856 -/+ buffers/cache: 1259848 6796336 Swap: 4194300 0 4194300
メモリ使用量の増加分は 192MB 程度です。
% LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; 10.times{fork{sleep}}; sleep 1; system "free"' total used free shared buffers cached Mem: 8056184 2084772 5971412 67856 372892 613568 -/+ buffers/cache: 1098312 6957872 Swap: 4194300 0 4194300 total used free shared buffers cached Mem: 8056184 4041740 4014444 67856 372892 613568 -/+ buffers/cache: 3055280 5000904 Swap: 4194300 0 4194300
jemalloc 使うと 2GB 程メモリを食ってしまっています。
なんでこういうことになるのか理屈は全然わかってませんが、jemalloc 使うことでメモリに悪影響を及ぼすこともあるという例でした。
まあ fork なんて使うのが悪いのかもしれませんけどね。