2006年09月14日

DBサーバ向けLinuxチューニングを考える 〜 メモリオーバーコミット編

はてなブックマークに登録

Cでプログラムを書いていて大量のメモリを確保したくなったとき、大抵は mallocを使うと思いますが、その際には戻り値がNULLかどうかを判断してエラー処理に飛ばすと思います。しかし、Linux のメモリ管理サブシステムには「メモリ・オーバーコミット」という機構があり、実装されているメモリ以上の領域を確保できてしまいます。

試しに以下のような簡単なコード (alloctest.c) を書いてみます。


#include <stdio.h>
#include <stdlib.h>

int main()
{
int i;
char *p;
for(i=0;i<65536;i++){
p = (char *)malloc(65536);
if(0 == (long)p){
break;
}
}
printf("SIZE=%dMB\n",i*65536/1024/1024);
return(0);
}



swapoff したメモリ 1G のマシンでこれを実行するとこんな感じになります。


$ gcc -o alloctest alloctest.c
$ ./alloctest
SIZE=3052MB



ちなみに free の結果はこんな感じです。


$ free -m
total used free shared buffers cached
Mem: 938 728 209 0 191 118
-/+ buffers/cache: 418 519
Swap: 0 0 0



なんと 1G のマシンなのに 3G もの領域を確保することができてしまいました。
Linux の仮想メモリシステムでは、プロセスがメモリを確保する際にはたくさんあるように見せかけておいて、実際にアクセスが発生した時に物理メモリを割り当てています。これは、「念のためいっぱいメモリを確保しておくけど実際はそんなに使わないプロセス」が複数動いているときなどに、ハードウエアリソースを有効活用するための優れた仕組みといえます。

それでは、実際にメモリ不足が起きたらどうなってしまうのでしょうか。
ここで登場するのが有名な「OOM Killer」という仕組みです。
Linux が実際にメモリ不足に陥ると、とあるアルゴリズムでいくつかのプロセスを選択し、それを勝手に kill してしまいます。kill されるプロセスは、自分が何故落とされるのかを知る由がありません。

つまり、malloc の結果を見てメモリ不足のエラー処理をしていたとしても、実際にその処理が走る事はないのです。Linux 上で動いている全てのプロセスは、システムがメモリ不足になっていても気にせずに動作しつづけてしまい、その裏では OOM Killer がせっせとプロセスを停止しているわけです。

時と場合によってはパフォーマンス面において OOM Killer が有効な事もありますので、必ずしもこの仕組みが悪いとはいいませんが、ただ、MySQL や PostgreSQL などの DBサーバでこの機構が動いてくれるのは嬉しいことではありません。メモリ不足が原因で強制的にプロセスが落とされるくらいなら、 DBサーバ自身でメモリ不足を検出してエラー処理をしたほうが安全ではないでしょうか。

カーネル2.6では、以下のコマンドでこの動作を制御することができるようになっています。


# sysctl -w vm.overcommit_ratio=99
# sysctl -w vm.overcommit_memory=2



/proc/sys/vm/overcommit_ratio で確保できる物理メモリの割合を指定します。
/proc/sys/vm/overcommit_memory を 2にするとメモリオーバーコミットを許さなくなります。

※overcommit_ratio のデフォルト値は 50 です。指定しないままだと搭載メモリの半分までしか確保できなくなってしまいますのでご注意下さい。でないとあちらこちらでメモリ不足がではじめます。

この状態で先ほどの alloctest を実行してみます。


$ ./alloctest
SIZE=428MB



実際の空き容量しか確保できなくなったようです。

MySQLのパフォーマンスチューニングなどをする際には、overcommit_memory=2 にして確保できるメモリサイズを制限しておきます。メモリが足りなくなったら Out Of Memory で MySQL が自分で落ちるようになりますので、実際にどれだけのメモリを必要としているかがわかるようになります。
これでバッファサイズなどのパラメータ調整が容易になるのではないでしょうか。


参考

/proc/sys/vm/* に関する文書

klab_gijutsu2 at 17:13│Comments(2)TrackBack(0)kernel | mysql

トラックバックURL

この記事へのコメント

2. Posted by imsut   2006年12月06日 20:41
こんにちは。OOM Killerのことは始めて知りました。勉強になります。

> MySQLのパフォーマンスチューニングなどをする際には、overcommit_ratio=2 にして

「overcommit_memory=2にして」ではないでしょうか? _ratio=2だと、恐ろしいことになりそうです。
3. Posted by Yasui   2006年12月06日 21:18
おおおおぉ・・

imsutさん、ご指摘ありがとうございます。
本文を修正しました。
たしかに ratio=2 にすると恐ろしいことになりますね(^^;

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント