Benchmarking Patterns
Write reliable micro-benchmarks using os.clock and avoid common pitfalls.
Benchmarking Patterns is a free Lua Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Benchmark?
Micro-benchmarks measure the performance of a specific code snippet in isolation. They help verify that an optimization actually improves speed without relying on intuition.
Basic Benchmark Template
Wrap the code in a loop, measure wall time with os.clock(), and divide by iteration count.
local N = 1e6
local t0 = os.clock()
for i = 1, N do
-- code to benchmark
end
local elapsed = os.clock() - t0
print(("%.2f ns/op"):format(elapsed / N * 1e9))Warm-Up Pass
Run a warm-up pass before timing to let LuaJIT compile traces. Without warm-up, the first timed run includes JIT compilation overhead.
for i = 1, 1000 do hotFunction(i) end -- warm up
local t0 = os.clock()
for i = 1, N do hotFunction(i) end
local elapsed = os.clock() - t0Preventing Dead-Code Elimination
The JIT may optimize away computations whose results are unused. Accumulate results into a variable to keep the benchmark honest.
local sum = 0
for i = 1, N do sum = sum + math.sin(i) end
print(sum) -- prevent eliminationComparing Two Approaches
Benchmark alternative implementations under identical conditions. Run them interleaved or multiple times to minimize OS scheduling noise.
local function approach1() -- ...
end
local function approach2() -- ...
end
local function bench(fn, n)
local t = os.clock()
for _ = 1, n do fn() end
return os.clock() - t
end
print("A:", bench(approach1, 1e5))
print("B:", bench(approach2, 1e5))Statistical Analysis
Run the benchmark multiple times and compute min, max, and median. Outliers from GC pauses or OS scheduling should be discarded.
Memory Benchmarking
Measure memory allocation alongside timing.
collectgarbage("collect")
local mem0 = collectgarbage("count")
-- ... run operation ...
collectgarbage("collect")
local mem1 = collectgarbage("count")
print(("Memory delta: %.1f KB"):format(mem1 - mem0))Avoiding GC Interference
Stop the GC before timing to measure pure computation time. Resume it after.
collectgarbage("stop")
local t0 = os.clock()
for i = 1, N do -- ... end
print(os.clock() - t0)
collectgarbage("restart")Realistic vs Micro Benchmarks
Micro-benchmarks optimize small snippets but may not reflect real-world performance. Always validate improvements against a full application profile.
Benchmark Utilities
Build a reusable benchmark(name, fn, iters) utility that prints consistent, formatted results across all your benchmarks.
local function benchmark(name, fn, iters)
iters = iters or 1e5
for _ = 1, iters // 10 do fn() end -- warm up
local t = os.clock()
for _ = 1, iters do fn() end
local ns = (os.clock() - t) / iters * 1e9
print(("%-30s %8.1f ns/op"):format(name, ns))
endCI Benchmarking
Run benchmarks in CI to detect performance regressions. Alert if a benchmark degrades by more than a defined threshold (e.g., 10%).
Benchmark Question
Why is a warm-up pass important when benchmarking LuaJIT code?
Recap: Benchmarking Patterns
Use a warm-up pass, prevent dead-code elimination by using results, measure with os.clock(), control GC, and run multiple trials for stable measurements. Build a reusable benchmark utility for consistency.
Frequently asked questions
Is the “Benchmarking Patterns” lesson free?
Yes — the full text of “Benchmarking Patterns” is free to read here on the web, and the Lua Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Lua Academy course, upgrade to CoddyKit PRO.
What will I learn in “Benchmarking Patterns”?
Write reliable micro-benchmarks using os.clock and avoid common pitfalls. You practise Lua Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Lua Academy?
No prior experience is required. Lua Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Benchmarking Patterns” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Lua Academy lesson?
Yes. Every Lua Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- LuaJIT Architecture Overview
- Writing JIT-Friendly Lua
- Profiling with jit.p and perf
- Benchmarking Patterns