Check out how OpenResty XRay helps organizations troubleshoot issues and optimize the performance of their applications.

Learn More LIVE DEMO

This tutorial demonstrates how to pre-compile Lua modules into LuaJIT bytecode. This can help reduce the startup time of an OpenResty application.

export PATH=/usr/local/openresty/bin:$PATH
cd ~
mkdir -p precomp
cd precomp/

screenshot 1

Here we will use a big Lua module file named pkg-stap.lua. It was generated by our opslang compiler.

cp ~/git/opslang/pkg-stap.lua ./
ls -lh *.lua

screenshot 2

We can see that this Lua module is 1.6MB.

Let’s try loading this Lua module with the resty utility.

time resty -I. -e 'require "pkg-stap"'

screenshot 4

It takes 23 milliseconds in total.

Let’s check the original overhead of running an empty Lua program.

time resty -e ''

screenshot 6

It is about 11 milliseconds. So loading the module itself takes about 12 milliseconds.

Let’s try precompiling the Lua module into LuaJIT bytecode.

time /usr/local/openresty/luajit/bin/luajit -bg pkg-stap.lua pkg-stap.ljbc

screenshot 8

Here we use OpenResty’s luajit program.

It generates a LuaJIT bytecode file with the .ljbc file extension.

ls -lh *.ljbc

screenshot 10

It’s fun to see the bytecode file is also more than 50% smaller!

Then try loading it with resty again.

time resty -I. -e 'require "pkg-stap"'

screenshot 12

Just 13 milliseconds in total!

It’s now almost like loading an empty Lua program! Only about 2 milliseconds extra.

time resty -e ''

screenshot 14

The resty utility always tries to load an .ljbc file before a .lua file when loading a module.

Let’s see how to make it work for an OpenResty server.

mkdir conf logs lua

screenshot 16

Copy our Lua module files to the lua/ subdirectory.

mv *.lua *.ljbc lua/
tree .

screenshot 17

Write a simple nginx configuration file, conf/nginx.conf. We make the following edits:

  1. Use a single worker process.
  2. Use 1024 worker connections.
  3. In the lua_package_path directive, it is important to try .ljbc files before .lua files. You can also try keeping the .ljbc files only to be sure.
  4. Inside init_by_lua_block, we preload our modules so that any module loading failures can be caught upon server startup. This also leads to faster first requests, and smaller memory footprint due to the COW optimization.
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"; }
    }
}

Check the directory tree.

tree .

screenshot 26

Looking good!

Try testing the server configuration using the -t option.

time openresty -p $PWD/ -t

Start it up.

time openresty -p $PWD/

screenshot 29

About 7 milliseconds.

Try removing the LuaJIT bytecode file.

rm lua/*.ljbc

screenshot 31

Stop the server.

kill -QUIT `cat logs/nginx.pid`

screenshot 32

Start the server again.

time openresty -p $PWD/

screenshot 33

This time it is 17 milliseconds! We can see it is 10 milliseconds slower too by loading the Lua source file.

Finally, try removing the Lua source files too.

rm lua/*.lua

screenshot 35

Stop the server and start it again.

time openresty -p $PWD/

screenshot 36

This time, we get an error as expected since both versions of the module are gone.

For small Lua module files, it is already very fast to load their source code.

echo 'local _M = {} function _M.foo() end return _M' > a.lua
ls -l a.lua
time resty -I. -e 'require "a"'

screenshot 38

Precompiling a small Lua module file won’t help much.

time /usr/local/openresty/luajit/bin/luajit -bg a.lua a.ljbc
time resty -I. -e 'require "a"'

screenshot 39

Indeed not much. But the time saving can accumulate quickly if you have many small modules to load up.

If you like this tutorial, please subscribe to this blog site and our YouTube channel. Thank you!

About The Author

Yichun Zhang (Github handle: agentzh), is the original creator of the OpenResty® open-source project and the CEO of OpenResty Inc..

Yichun is one of the earliest advocates and leaders of “open-source technology”. He worked at many internationally renowned tech companies, such as Cloudflare, Yahoo!. He is a pioneer of “edge computing”, “dynamic tracing” and “machine coding”, with over 22 years of programming and 16 years of open source experience. Yichun is well-known in the open-source space as the project leader of OpenResty®, adopted by more than 40 million global website domains.

OpenResty Inc., the enterprise software start-up founded by Yichun in 2017, has customers from some of the biggest companies in the world. Its flagship product, OpenResty XRay, is a non-invasive profiling and troubleshooting tool that significantly enhances and utilizes dynamic tracing technology. And its OpenResty Edge product is a powerful distributed traffic management and private CDN software product.

As an avid open-source contributor, Yichun has contributed more than a million lines of code to numerous open-source projects, including Linux kernel, Nginx, LuaJIT, GDB, SystemTap, LLVM, Perl, etc. He has also authored more than 60 open-source software libraries.