さてさて、これまでの研究の論文化や研究会発表等が落ち着いたので、mod_mruby触ってます。
前回、mod_luaにパフォーマンス面で完敗したわけですが、ついにやりました。mod_luaを超えてやりましたよ!
工夫した所
何を変えたかいうと、前回の実装ではmrubyスクリプト実行毎に、
- mrb_open()実行
- mrb_define_module()やmrb_define_class_method()を実行
- mrb_parse_file()実行
- mrb_generate_code()実行
- mrb_run()実行
していました。しかし、Apacheの特性上プロセスやスレッドをプールさせて使いまわすため、少なくとも1と2のルーチンは使いまわせるんじゃないか、ということで、各サーバプロセスの生成時にInitializedのルーチン内で一度だけ実行するようにしました。
さらに、これだけでは足りないので、mrb_generate_codeやmrb_parse_fileをキャッシュして使いまわせるようなキャッシュテーブルを用意して、一度実行した事のあるmrubyスクリプトはそのデータをキャッシュテーブルのスロットに入れて使いまわすようにしました。これは、mrubyでApacheモジュールを実装した際には、頻繁にスクリプト変更はしないだろう、という考えから生まれたアイデアです。
というのは、mod_mrubyはWebコンテンツをmrubyで実装することも可能ですが、本来は、ApacheモジュールをCで実装する代わりに、mrubyスクリプトで実装して簡単にサーバの機能を組み込めて、かつ、保守性が高い事を目的としていたためです。mrubyを採用したのも、組み込みスクリプトを目的としていて高速なためです。
また、stat()でファイルの変更をチェックして変更があった場合は、キャッシュテーブルのスロットを更新させるようにしてみました。この辺りは、まだ未完成なのでなんちゃっての実装になっています。今後、キャッシュの時間やキャッシュヒットの多いスロットを優先して残すような仕組みを実装しようかな、と思っています。
何はともあれ、この工夫によって以下のような性能を出すことができました。計測の仕方は前回と同様です。
環境設定
mod_mrubyとmod_luaをコンパイルして、以下のように組み込みました。
- mod_mrubyの設定
LoadModule mruby_module modules/mod_mruby.so
AddHandler mruby-script .mrb
- mod_luaの設定
Loadmodule lua_module modules/mod_lua.so
AddHandler lua-script .lua
aそして、それぞれのベンチスクリプトは、シンプルに以下のようにしました。
- mrubyスクリプト
require 'Apache'
Apache.rputs("hello world!")
- luaスクリプト
require "apache2"
function handle(r)
r:puts("hello world!")
end
mod_luaはApacheから呼び出される際には、handleファンクションを見に行くような実装になっているので、上記のようにしました。
計測結果
純粋にどの程度の速度で処理が可能なのかを知るために、それぞれがある程度余裕をもって処理できるパラメータを見つけて、複数回ベンチマークをとってみました。今回はキャッシュテーブルが未完成だったので、キャッシュ機能はOFFにしています。
以下のようなabコマンドでrequest per sec(1秒間に処理できたリクエスト数)を10回分比較しました。同時接続数100で総接続数は3000です。
ab -c 100 -n 3000 http://ipaddr/hello.lua | grep "Requests per second"
ab -c 100 -n 3000 http://ipaddr/hello.mrb | grep "Requests per second"
それでは、mod_mruby vs mod_luaの結果はどうなったのでしょうか!
はい、結果は以下のようになりました。
mod_mruby | mod_lua | |
1回目(response/sec) | 14369.19 | 8544.23 |
2回目 | 16538.86 | 6871.56 |
3回目 | 14717.35 | 9704.84 |
4回目 | 10847.16 | 8150.38 |
5回目 | 17139.53 | 7949.72 |
6回目 | 16615.62 | 9520.24 |
7回目 | 15498.51 | 8264.67 |
8回目 | 13982.36 | 8163.07 |
9回目 | 16327.24 | 8405.13 |
10回目 | 12253.95 | 7867.84 |
どうでしょうか、前回とは違ってmod_luaよりもmod_mrubyの方が大分早くなったことが分かります。これで、組み込みスクリプトであるmrubyの性能を利用して、Apacheモジュールをmrubyスクリプトで書く時代がやってくるのも、そう遅くないかもしれません。
とりあえず、速度面でキャッシュテーブルを実装することでさらに性能を向上させた後は、request_recやserver_rec構造体をmrubyとApache間で連携するインターフェイスを作って、mrubyスクリプトをフックされる箇所を増やしていこうと思います。
「mod_mrubyの逆襲(mod_luaよりパフォーマンス良くなったよ)」への3件のフィードバック
コメントは受け付けていません。