memcachedを知り尽くす

第2回 memcachedのメモリストレージを理解する

この記事を読むのに必要な時間:およそ 4 分

Slab Allocatorの弱点

Slab Allocatorの開発により,当初の課題であったフラグメンテーション問題は解消されましたが,新たなメカニズムにより新しい課題がmemcachedに生まれました。

その問題は,固定長なメモリ確保のアプローチにより,確保したメモリを有効活用できないということです。例えば100バイトのデータを128バイトのchunkにキャッシュすると,余りの28バイトが無駄になります図3⁠。

図3 chunkの領域使用

図3 chunkの領域使用

この問題に対する完全なソリューションは現状存在しませんが,ドキュメントに効率的なソリューションが記載されています:

The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all possible) common sizes of objects that the clients of this particular installation of memcached are likely to store.

つまり,クライアントが送ってくるデータの共通サイズがあらかじめ解っている,もしくは同じサイズのデータしかキャッシュしないユースケースであれば,そのサイズに適したクラスのリストを使い,無駄を抑えることが可能ということです。

ただし残念なことに,現状ではこのチューニングを行うことはできず,将来の課題として残っています。しかしながら,slab classたちのサイズ差をチューニングすることは可能なので,次にgrowth factorオプションについて説明します。

Growth Factorを使ったチューニング

memcachedはスタートアップ時にGrowth Factorという因子を指定して(-f オプション⁠⁠,slab間のサイズをある程度制御することが可能です。デフォルト値は1.25ですが,このオプションが開発される以前は⁠powers of 2⁠戦略といって,2が固定でした。

では,実際に以前の設定でmemcachedをverboseモードで起動してみましょう:

$ memcached -f 2 -vv

以下がスタートアップ後のverbose出力です:

slab class   1: chunk size    128 perslab  8192
slab class   2: chunk size    256 perslab  4096
slab class   3: chunk size    512 perslab  2048
slab class   4: chunk size   1024 perslab  1024
slab class   5: chunk size   2048 perslab   512
slab class   6: chunk size   4096 perslab   256
slab class   7: chunk size   8192 perslab   128
slab class   8: chunk size  16384 perslab    64
slab class   9: chunk size  32768 perslab    32
slab class  10: chunk size  65536 perslab    16
slab class  11: chunk size 131072 perslab     8
slab class  12: chunk size 262144 perslab     4
slab class  13: chunk size 524288 perslab     2

ご覧の通り,128バイトのクラスから始まって,クラスのサイズが2倍づつ大きくなっています。この設定の問題は,slab間の差が比較的に大きいため,ユースケース次第で相当なメモリが無駄に消費されることです。そういった背景から問題をなるべく解消するためにgrowth factorオプションが2年前に追加されました。

では,現在のデフォルト設定(f = 1.25)の出力を見てみましょう(長いのでクラス10まで⁠⁠:

slab class   1: chunk size     88 perslab 11915
slab class   2: chunk size    112 perslab  9362
slab class   3: chunk size    144 perslab  7281
slab class   4: chunk size    184 perslab  5698
slab class   5: chunk size    232 perslab  4519
slab class   6: chunk size    296 perslab  3542
slab class   7: chunk size    376 perslab  2788
slab class   8: chunk size    472 perslab  2221
slab class   9: chunk size    592 perslab  1771
slab class  10: chunk size    744 perslab  1409

ご覧の通り,クラスのサイズ差が因子を2で起動した場合より小さく,数百バイトのレコードをキャッシュするのにより適していることが解ります。また,この出力をみてサイズ計算に若干の誤差があると感じた方もいるかもしれませんが,この誤差は内部的にバイト数のアライメントを保つために故意に行われています。

memcachedをプロダクションに導入することを検討している,もしくは考えずにデフォルトでデプロイしている場合は,ぜひ一度,平均データサイズの予想値を計算して,growth factorのチューニングでそのユースケースで最適なセッティングを調べることをおすすめします。メモリは貴重なリソースなので,無駄に使うにはもったいないです。

次にmemcachedのstatsを使ってslabsの利用率や色々な情報を調べる方法を紹介します。

著者プロフィール

前坂徹(まえさか とおる)

株式会社ミクシィ 研究開発グループにて,オープンソース技術の開発・検証を担当しています。memcachedの開発コミュニティのメンバーでもあり,現在は1.3シリーズの開発に携わっています。

URLhttp://torum.net/