OpenResty の起動速度を向上させるための Lua モジュールの LuaJIT バイトコードへの事前コンパイル
このチュートリアルでは、Lua モジュールを LuaJIT バイトコードに事前コンパイルする方法を説明します。これにより、OpenResty アプリケーションの起動時間を短縮することができます。
export PATH=/usr/local/openresty/bin:$PATH
cd ~
mkdir -p precomp
cd precomp/
ここでは、大規模な Lua モジュールファイル pkg-stap.lua
を使用します。これは、当社の opslang コンパイラによって生成されたものです。
cp ~/git/opslang/pkg-stap.lua ./
ls -lh *.lua
この Lua モジュールのサイズが 1.6MB であることがわかります。
resty
ツールを使用してこの Lua モジュールをロードしてみましょう。
time resty -I. -e 'require "pkg-stap"'
合計で 23 ミリ秒かかります。
空の Lua プログラムを実行する際の基本的なオーバーヘッドを確認してみましょう。
time resty -e ''
約 11 ミリ秒です。つまり、モジュールのロード自体に約 12 ミリ秒かかっていることになります。
Lua モジュールを LuaJIT バイトコードに事前コンパイルしてみましょう。
time /usr/local/openresty/luajit/bin/luajit -bg pkg-stap.lua pkg-stap.ljbc
ここでは、OpenResty の luajit
プログラムを使用します。
これにより、拡張子が .ljbc
の LuaJIT バイトコードファイルが生成されます。
ls -lh *.ljbc
興味深いことに、バイトコードファイルのサイズが 50% 以上小さくなっていることがわかります!
次に、resty
を使用して再度ロードしてみましょう。
time resty -I. -e 'require "pkg-stap"'
合計でわずか 13 ミリ秒です!
今や、ほぼ空の Lua プログラムをロードするのと同じくらいの速さです!わずか 2 ミリ秒の差しかありません。
time resty -e ''
モジュールをロードする際、resty ツールは常に .lua
ファイルの前に .ljbc
ファイルのロードを試みます。
OpenResty サーバーでこれを機能させる方法を見てみましょう。
mkdir conf logs lua
Lua モジュールファイルを lua/
サブディレクトリにコピーします。
mv *.lua *.ljbc lua/
tree .
簡単な nginx 設定ファイル conf/nginx.conf
を作成します。以下のように編集します。
- 単一の nginx ワーカープロセスを有効にします。
- ワーカープロセスごとに 1024 の接続を使用します。
lua_package_path
ディレクティブでは、.lua
ファイルの前に.ljbc
ファイルを試すことが重要です。.ljbc
ファイルのみを残して試すこともできます。init_by_lua_block
では、モジュールを事前にロードしています。これにより、モジュールのロードに失敗した場合、サーバー起動時に検出できます。また、これにより最初のリクエストが高速化され、COW
最適化によりメモリ使用量も削減されます。
worker_processes 1;
events {
worker_connections 1024;
}
http {
lua_package_path "$prefix/lua/?.ljbc;$prefix/lua/?.lua;;";
init_by_lua_block {
require "pkg-stap"
}
server {
listen 8080;
location / { return 200 "ok\n"; }
}
}
ディレクトリツリーを確認します。
tree .
問題ありません!
-t
オプションを使用してサーバー設定をテストしてみましょう。
time openresty -p $PWD/ -t
サーバーを起動します。
time openresty -p $PWD/
約 7 ミリ秒かかりました。
LuaJIT のバイトコードファイルを削除してみましょう。
rm lua/*.ljbc
サーバーを停止します。
kill -QUIT `cat logs/nginx.pid`
サーバーを再度起動します。
time openresty -p $PWD/
今回は 17 ミリ秒かかりました!Lua ソースファイルを読み込むことで、10 ミリ秒遅くなったことがわかります。
最後に、Lua ソースファイルも削除してみましょう。
rm lua/*.lua
サーバーを停止し、再起動します。
time openresty -p $PWD/
今回は、両方のバージョンのモジュールが見つからないため、予想通りのエラーが発生しました。
小さな Lua モジュールファイルの場合、そのソースコードを読み込むのは既にかなり高速です。
echo 'local _M = {} function _M.foo() end return _M' > a.lua
ls -l a.lua
time resty -I. -e 'require "a"'
小さな Lua モジュールファイルをプリコンパイルしても、大きな効果は得られません。
time /usr/local/openresty/luajit/bin/luajit -bg a.lua a.ljbc
time resty -I. -e 'require "a"'
確かに大きな違いはありません。しかし、多数の小さなモジュールを読み込む必要がある場合、節約される時間はすぐに積み重なっていきます。
著者について
章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。
章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵襲的な障害分析および排除ツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能
翻訳
英文版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!