アドサーバ開発でのLuaの利用 連載(2)

Pocket

こんにちは。技術開発部で部長をしている伊良子と申します。

前回は、Luaを採用した経緯/理由について書くことで、Lua及びngx_luaの紹介をさせて頂きました。連載第二回の今回はngx_luaをより高速に動作させるためのTIPSをご紹介したいと思います。

LuaJITを利用する

Luaの最新バージョンは5.3ですが、ngx_luaがサポートしているのは5.1までです。ngx_luaは、このLua5.1を使用するよりもJITコンパイラ版であるLuaJITの使用を推奨しています。LuaJITはLua5.1系に対応した本家Luaとは別のプロジェクトで、本家Luaと比べて高速に動作します。
弊社でもngx_luaを利用し始めた当初は本家Luaを使用していたのですが、LuaJITに切り替えた際には1.3倍以上のパフォーマンス向上となりました。実際のアプリケーションでの速度比較なため、速度低下の要因は様々あるにも関わらずLuaJITに変えただけで1.3倍高速になったのには驚きました。

ngx_luaでの利用ではありませんが、本家LuaとLuaJITでベンチマーク比較してみましょう。

フィボナッチ数列の40番目の数を求めるプログラムで比較してみます。このような処理だと上記したような実際のWebアプリケーションと違い、処理系のみの比較となります。

LuaJITが10倍の速度差で圧勝しました。

ngx.shared.DICTの利用

ngx.shared.DICTは、子プロセス間で共通に使える記憶領域です。

のような形で使えます。memcachedと似たような利用方法になりますが、特筆すべきはその速度です。memcachedとngx.shared.DICTを、ApacheBencheを使った比較です。

memcachedでSET/GETを30回づつ行った場合:400〜500req/sec
同様のSET/GETをngx.shared.DICTで行った場合: 1200〜1400/sec
何もしないでレスポンスだけ返す場合: 1300〜1400req/sec

ngx.shared.DICTを使った場合は、何もしない場合と変わらない速度で動作しました。直接メモリーを読み書きするため非常に高速です。弊社では、memcachedのキャッシュとして利用しています(キャッシュのキャッシュ)

ngx.varやngx.req.XXXを何度も呼ばない

ngx.varやngx.reqは、参照するたびに、ngx.var.全XXX、ngx.req.全XXXを展開する仕様であるらしく、参照のコストが高いです。

のように一度だけ参照して、以後はその変数(テーブル)を使いまわすようにします。

os.timeではなくngx.timeを使う

luaの標準ライブラリであるos.timeを使うと、使う度にシステムコールが発生してしまいますが、ngx.timeを使えばnginxがキャッシュした時間を返すため高速です。

今回はこの辺で。
ネタもなくなってきたので次回でLuaは最終回とさせて頂きます。

アドサーバ開発でのLuaの利用 連載(1)
アドサーバ開発でのLuaの利用 連載(3)
lua-resty-httpを利用したCookieの操作