Lua Academy · Lesson

Writing JIT-Friendly Lua

Avoid JIT bailouts: keep types stable, minimize table resizing, use locals.

Lesson 2 of 413 steps

Writing JIT-Friendly Lua is a free Lua Academy lesson on CoddyKit. This is lesson 2 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Lua Academy learning path, and your progress syncs across the web and the CoddyKit app. The Lua Academy course includes 4 lessons in total.

Why JIT-Friendliness Matters

The JIT compiler works best on type-stable, predictable code. Unpredictable types and branching cause trace aborts and bailouts, reverting to the interpreter.

Keep Types Stable

A variable should always hold the same type. If a variable alternates between number and string, the JIT cannot specialize and must insert type checks everywhere.

-- BAD: type unstable
local x = 1
if cond then x = "one" end  -- JIT cannot specialize x

-- GOOD: separate variables
local xNum = 1
local xStr = "one"

Use Local Variables

Local variables are stored on the Lua stack (register-allocated by JIT). Global and upvalue access is slower. Cache globals as locals at the top of hot functions.

local sin = math.sin  -- cache as local
for i = 1, 1e6 do
  result = sin(i)  -- fast local access
end

Avoid Table Resizing in Loops

Pre-allocate tables to their expected size. Growing a table in a loop (crossing the next power-of-2 boundary) reallocates and copies the array, breaking JIT traces.

local t = table.new(1000, 0)  -- LuaJIT extension
for i = 1, 1000 do t[i] = i end

Avoid Mixed Array/Hash

Keep array parts as arrays (integer keys from 1). Mixing integer and string keys in the same table prevents array optimizations.

Avoid Closures in Hot Inner Loops

Creating a new closure on each iteration allocates memory and can cause GC pressure. Pre-allocate closures outside the loop.

-- BAD: closure created every iteration
for i = 1, 1e6 do
  local fn = function() return i end  -- allocation!
end

-- GOOD: use a local function outside
local function work(i) return i end
for i = 1, 1e6 do work(i) end

Avoid Polymorphic Calls

Calling different function objects through the same call site (different functions each iteration) creates a polymorphic call site the JIT cannot inline.

Avoid NYI (Not Yet Implemented) Features

Some Lua features are not implemented in LuaJIT's JIT (NYI): string.format with some specifiers, pcall inside JIT traces, pairs/next. Check jit.v output.

jit.v for Trace Verbosity

Enable verbose JIT output to see which traces are compiled and which abort.

-- Run script with: luajit -jv script.lua
-- Or in code:
jit.attach(function(event, ...)
  if event == "abort" then print("ABORT:", ...) end
end, "all")

Use Fixed-Size Arrays

When an array has a known fixed size, declaring it as a constant-size C array via FFI can be dramatically faster than a Lua table.

Profile Before Optimizing

Measure first. Premature optimization is the root of all evil. Profile to find the actual hot path before spending time on JIT-friendly rewrites.

JIT-Friendly Question

Why should you avoid creating closures inside hot inner loops?

Recap: JIT-Friendly Lua

Keep types stable, use locals, pre-allocate tables, avoid closures in hot loops, and check for NYI features with jit.v. Profile first — optimize only proven bottlenecks.

Free to start

Learn Lua with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
40
Lessons
159

Frequently Asked Questions

Is the “Writing JIT-Friendly Lua” lesson free?

Yes — any 3 lessons of the Lua Academy learning path, including “Writing JIT-Friendly Lua”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Lua Academy course includes 4 lessons in total.

What will I learn in “Writing JIT-Friendly Lua”?

Avoid JIT bailouts: keep types stable, minimize table resizing, use locals. 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, so you can start here or from the beginning and move at your own pace. This is lesson 2 of 4.

How long does the “Writing JIT-Friendly Lua” 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

  1. LuaJIT Architecture Overview
  2. Writing JIT-Friendly Lua
  3. Profiling with jit.p and perf
  4. Benchmarking Patterns
← Back to Lua Academy