Introduction
Lua excels in embedded environments and games thanks to its lightweight nature. In 2026, performance demands require deep mastery of metatables, coroutines, and LuaJIT. This tutorial guides you step by step toward concrete, measurable optimizations.
Prerequisites
- Lua 5.4 or LuaJIT 2.1+
- Solid knowledge of tables and functions
- C compiler for extensions
- Benchmarking tool like bench.lua
Advanced Dynamic Metatables
local mt = {
__index = function(t, k)
if k == "computed" then return t.base * 2 end
return rawget(t, k)
end,
__newindex = function(t, k, v)
if k == "locked" then error("Champ verrouillé") end
rawset(t, k, v)
end
}
local obj = setmetatable({base = 10}, mt)
print(obj.computed) -- 20This metatable implements lazy computation and modification protection. It avoids infinite loops by using rawget/rawset.
Coroutines for Asynchronous Tasks
local co = coroutine.create(function()
for i = 1, 3 do
print("Étape", i)
coroutine.yield()
end
end)
coroutine.resume(co)
coroutine.resume(co)
coroutine.resume(co)Coroutines provide fine-grained flow control without OS threads. Each yield suspends execution and resumes exactly where it left off.
LuaJIT FFI Optimization
local ffi = require("ffi")
ffi.cdef[[
typedef struct { double x, y; } Point;
]]
local Point = ffi.typeof("Point")
local p = Point(1.0, 2.0)
print(p.x + p.y)LuaJIT's FFI enables calling native C code with zero overhead. Use it for critical loops to achieve near-C performance.
High-Performance Module
local M = {}
M.cache = setmetatable({}, {__mode = "v"})
function M.compute(key, fn)
if M.cache[key] then return M.cache[key] end
local res = fn()
M.cache[key] = res
return res
end
return MThis module implements a weak cache using mode 'v'. It prevents memory leaks while speeding up repeated calculations.
Benchmarking and Profiling
local start = os.clock()
for i = 1, 1000000 do
-- code à mesurer
end
print("Temps:", os.clock() - start)Use os.clock for precise measurements. Combine with LuaJIT -joff to compare JIT versus interpreted performance.
Best Practices
- Prefer local tables over globals
- Avoid creating closures in hot loops
- Use collectgarbage("count") to monitor memory
- Precompile scripts with luac -O3
- Always test with and without JIT
Common Mistakes to Avoid
- Forgetting rawget/rawset in metamethods creates infinite recursion
- Using coroutines with non-yield-safe resources
- Ignoring differences between Lua and LuaJIT in production
- Failing to clear weak caches regularly
Further Reading
Deepen your knowledge with our advanced Lua training.