KyotoTycoon では.so、.dylibといった共有ライブラリによるプラグインをサポートとして、プラグインとして、memcachedプロトコルを実装したプラグインや、msgpack-rpcで使えるようにした kt-msgpack がある。
kt-msgpack では、msgpack-rpc を利用しているので、同期的なProcedureの呼び出しはもちろん、非同期なProcedureの呼び出しや、レスポンスを返さない通知的なProcedureの呼び出しでKyotoTycoonのデータをいじれるようになっている。
ですがですが、ソースを見てみると、KyotoTycoonで提供しているProcedureがあまりにも少ないことが分かったので、git にあるプロジェクトをforkしてちょっと充実させてみた。
充実させたProcedureたち
今回の改造で、充実&追加したProcedureは以下な感じ。
- ping
- echo
- status
- add
- set
- get
- remove
- append
- seize
- clear
- replace
- cas
- increment
- increment_double
- match_prefix
- match_regex
- set_bulk
- remove_bulk
- get_bulk
- vacuum
- synchronize
データ操作系や検索系、そしてバルク操作系があるので、これぐらいあれば何とかことは足りるかと。
pingという変な名前のProcedureがありますが、これはvoidに相当し、msgpack-rpcの制約(というかIDLからC++のコードを生成するツールの制約?)でProcedureが別名にしています。
詳細はここのProceduresの一覧をご覧ください。
サポートしなかったProcedureたち
今回諸事情サポートしなかったProcedureは以下な感じ。
- report
- play_script
- tune_replication
- cur_jump
- cur_jump_back
- cur_step
- cur_step_back
- cur_set_value
- cur_remove
- cur_get_key
- cur_get_value
- cur_get
- cur_seize
- cur_delete
report、play_script、tune_replication はちょっと作りこみ(場合によってはKyotoTycoonをいじる必要があるかも)が必要なので今回は対応していない。
cur_xxx系は、KyotoTycoonのアーキテクチャとmsgpack-rpc(mpio)のアーキテクチャが異なっているので、実装するのはちょっとしんどい。KyotoTycoonではセッション毎にローカルストレージにcursorオブジェクトを保持することで対応できているのだが、msgpack-rpc(mpio)では、KyotoTycoonのような感覚でセッションを使える仕組みがないので、同じ機能の実装はmsgpack-rpcを改造でもしない限りちょっと辛いところだ。(というより、自分がmsgpack-rpcに同じような機能があるのを知らないだけ?)
そもそも、cursorの操作については、KyotoTycoonの作者のブログに書いてある意見と同じく、ネットワーク越しに長期間リソースを占有するようなものは、サーバのリソースの無駄遣いだと思う。そのようなことをしたい場合はplay_scriptのようなストアドプロシジャ的なスクリプトでcursor操作をして、さくっと用を足してしまえばいいと個人的に思っている。
なので、今後は、cur_xxx系のProcedureは対応しない方向で考えている。
パフォーマンス測定
せっかく、Procedureを充実させたんで、一番気になるバルク系のデータ操作のパフォーマンスを測ってみた。 計測は5回行い、平均値を計る。サーバ、クライアントは同じマシン上で測定した。
測定プログラム
KyotoTycoon をインストールした際にバンドルされてくるktremotetestとそれをkt-msgpackを向けに改変した、ktmpremotetestによって行う。
また、比較のためktremotetestで、KyotoTycoonのHTTPとBinaryも計測する。
ちなみに、ktmpremotetestは今回改造したこちらからgit cloneしてインストールすると、kt-msgpackといっしょにインストールされる。
マシン環境
マシン環境は以下のとおり。
- Macbook (13-inch, Early 2009)
- OS: Mac OS X Lion 10.7.3
- CPU: 2 GHz Intel Core 2 Duo
- Memory: 4 GB 667 MHz DDR2 SDRAM
- HDD: 256GB (FUJITSU MHZ2250BH FFS G1 Media SATA)
KyotoTycoonの起動オプション
KyotoTycoonの起動オプションは以下で起動する。
$ ktserver -th 8 -lz -plsv /opt/local/libexec/libktmsgpack.dylib -plex "port=18801#thread=8" "casket.kct#bnum=2000000#opts=ls#ktopts=p"
- バケット数は100万レコードの2倍値(bnum=2000000)
- データベースオプションは、4バイトアドレッシング、線形リスト(opts=ls)
- パフォーマンスをちゃんと計測するために、KyotoTycoon側のスレッド数とkt-msgpackプラグインのスレッド数を同じ値に設定(-th 8, thread=8)
- ログ出力はなし(-lz)
- データは永続化(ktopts=p)
測定内容
KyotoTycoonの作者のこの記事と同じことをする。サーバに対して、「00000001」「00000002」といった文字列のキーと値を持つレコード合計100万件の読み書きを行う。 以下のコマンド、set系9パターン、get系9パターン、計18パターンを計測する。
- ktremotetest bulk -th 4 -set -bulk 1 250000
- ktremotetest bulk -th 4 -set -bulk 10 250000
- ktremotetest bulk -th 4 -set -bulk 100 250000
- ktremotetest bulk -th 4 -set -bin -bulk 1 250000
- ktremotetest bulk -th 4 -set -bin -bulk 10 250000
- ktremotetest bulk -th 4 -set -bin -bulk 100 250000
- ktmpremotetest bulk -th 4 -set -bulk 1 250000
- ktmpremotetest bulk -th 4 -set -bulk 10 250000
- ktmpremotetest bulk -th 4 -set -bulk 100 250000
- ktremotetest bulk -th 4 -get -bulk 1 250000
- ktremotetest bulk -th 4 -get -bulk 10 250000
- ktremotetest bulk -th 4 -get -bulk 100 250000
- ktremotetest bulk -th 4 -get -bin -bulk 1 250000
- ktremotetest bulk -th 4 -get -bin -bulk 10 250000
- ktremotetest bulk -th 4 -get -bin -bulk 100 250000
- ktmpremotetest bulk -th 4 -get -bulk 1 250000
- ktmpremotetest bulk -th 4 -get -bulk 10 250000
- ktmpremotetest bulk -th 4 -get -bulk 100 250000
-thは、起動スレッド数を意味する。
-setはset_bulkによるレコード設定を意味する。
-getはget_bulkによるレコード設定を意味する。
-bulkは、バルク操作で一度に設定/取得するレコード数を意味する。
ktremotetestの-binはBinaryプロトコルによるバルク設定/取得を意味する。このオプションがない場合は、HTTPプロトコルによるバルク設定/取得になる。
測定結果
100万件のバルク操作の計測結果は以下のようになった。
| 計測1 | 計測2 | 計測3 | 計測4 | 計測5 | average | |
|---|---|---|---|---|---|---|
| 1.HTTP set 1 bulk | 124.643 | 126.641 | 119.626 | 125.788 | 140.967 | 127.533 |
| 2.HTTP set 10 bulk | 20.731 | 17.873 | 15.776 | 16.058 | 15.281 | 17.1438 |
| 3.HTTP set 100 bulk | 7.052 | 6.719 | 8.246 | 6.54 | 6.778 | 7.067 |
| 4.Binary set 1 bulk | 70.699 | 71.705 | 66.925 | 70.883 | 70.841 | 70.2106 |
| 5.Binary set 10 bulk | 8.44 | 9.193 | 8.939 | 9.877 | 8.776 | 9.045 |
| 6.Binary set 100 bulk | 4.449 | 4.923 | 4.341 | 4.412 | 4.309 | 4.4868 |
| 7.msgpack-rpc set 1 bulk | 78.078 | 85.017 | 79.846 | 77.657 | 87.636 | 81.6468 |
| 8.msgpack-rpc set 10 bulk | 16.943 | 14.585 | 13.157 | 13.645 | 17.013 | 15.0686 |
| 9.msgpack-rpc set 100 bulk | 7.261 | 7.19 | 6.894 | 7.659 | 10.003 | 7.8014 |
| 10.HTTP get 1 bulk | 117.963 | 124.22 | 122.057 | 120.705 | 132.164 | 123.4218 |
| 11.HTTP get 10 bulk | 16.756 | 19.225 | 18.153 | 18.522 | 21.171 | 18.7654 |
| 12.HTTP get 100 bulk | 8.068 | 8.733 | 11.251 | 9.193 | 9.028 | 9.2546 |
| 13.Binary get 1 bulk | 61.831 | 72.635 | 74.087 | 70.9 | 75.88 | 71.0666 |
| 14.Binary get 10 bulk | 9.883 | 10.741 | 11.739 | 10.249 | 13.278 | 11.178 |
| 15.Binary get 100 bulk | 5.861 | 7.47 | 6.11 | 6.061 | 6.048 | 6.31 |
| 16.msgpack-rpc 1 bulk | 79.438 | 89.539 | 74.367 | 92.129 | 91.659 | 85.4264 |
| 17.msgpack-rpc 10 bulk | 18.262 | 19.146 | 16.453 | 20.083 | 19.446 | 18.678 |
| 18.msgpack-rpc 100 bulk | 11.175 | 10.415 | 10.667 | 10.95 | 14.237 | 11.4888 |
やっぱり、Binaryがパフォーマンスいいですね。msgpack-rpcも結構いい感じパフォーマンスでています。この計測結果からみると、パフォーマンスとしては、
Binary > msgpack-rpc > HTTP
といった感じでしょうか。まあ、bulk操作で扱うデータ数を増やせば、まあそれなりの速度で処理することができるので、どれを利用しても実運用上特に問題ないかあと。同期、非同期の通信を柔軟に選択できつつ、パフォーマンスが確保できるっていうのがメリットなのかもしれない。(まあ、Node.jsを利用すれば、それできますけど。。。)
まとめ
kt-msgpackをforkして、KyotoTycoonで提供するProcedureを充実させました。この改造により他の言語でもmsgpack-rpcを利用することで、set、getによるデータ操作、バルク一括操作、検索、そしてcas、incrementが利用できるようになりました。msgpack-rpcのバルク操作のパフォーマンスも、HTTPとBinaryの間なので、通信機能で柔軟にロジックを制御したいっていう場合には、KyotoTycoonを使うユースケースでは、kt-msgpackを選択するのはいいかもしれません。

