memcached binary protocol
先日memcached Night in Tokyo #1に参加してきました。レプリケーションがアツイ。バイナリプロトコルがアツイ。
というわけでバイナリプロトコルのマイクロベンチマークをしてみました。
テストしたのは本家memcachedではなく、私が勝手に作ったストリームパーサです(すべてのプロトコルには対応していません)。get("key$i") と set("key$i", "value$i") を5,000,000回ずつリクエストしたときのプロトコルをファイルに保存しておき、mmap(2)してパースしました。
パーサとベンチマークに使ったプログラム一式はmemcached-protocol-bench.tar.gzからダウンロードできます。
- AMD Athlon 64 X2 5000+, Memory 4GB
- Linux 2.6.22.9 SMP x86_64
- gcc 4.2.2 最適化レベル-O4
リクエスト数 | サイズ | 時間 | 1リクエストにかかるパース時間 | 1秒間にパースできるリクエスト数 | |
---|---|---|---|---|---|
text | 1,000,000 | 23.5 MB | 0.49 sec | 0.49 μsec/request | 2,000,000 requests/sec |
binary | 1,000,000 | 40.2 MB | 0.033 sec | 0.033 μsec/request | 30,000,000 requests/sec |
keyもvalueも非常に小さいため、バイナリプロトコルのヘッダの大きさが目立ちます。バイナリプロトコルの方がずっと高速ですが、1リクエスト当たりの遅延の差は0.45μ秒と非常に小さく、ほぼゼロと考えてもいいのかもしれません。パーサの実装がマズイという可能性もなきにしもあらず ^_^;)
バイナリプロトコルの利点:
- キーに任意の文字を使える(テキストプロトコルは空白や\r\nが混入すると危険だし、そもそも制御文字は許可されていないので、base64する or エラーにする などの対処が必要)
- getは1度に1つのキーしかリクエストできないので、サーバーの実装がシンプルになる(get_multiはクライアント側でパイプライン処理して実装する)
- 何かに使える拡張用フィールド?がある
- 非同期プロトコルになり得る(クライアントから送られた値をそのまま返すopaqueフィールドがある)
※追記:tmaesakaさんの講演資料が公開されました:memcached Night #1 in Tokyo