Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Performance Tips

Maximize the performance of your Luau scripts on NicyRuntime.

1. Enable CodeGen/JIT

The single biggest performance improvement:

--!native
--!optimize 2

-- Your compute-intensive code here

Or compile with native code generation:

nicy compile myscript.luau --native --optimize 2

See CodeGen/JIT for details.

2. Use Local Variables

Local variables are significantly faster than globals:

-- Slow: Global access
function compute()
    math.sin(x)  -- Global lookup each call
end

-- Fast: Local reference
local sin = math.sin
function compute()
    sin(x)  -- Local access
end

3. Avoid Table Allocations in Loops

-- Bad: Creates a new table every iteration
for i = 1, 1000000 do
    local t = {x = i, y = i * 2}
    process(t)
end

-- Good: Reuse a single table
local t = {}
for i = 1, 1000000 do
    t.x = i
    t.y = i * 2
    process(t)
end

4. Use Integer Arithmetic When Possible

-- Slower: Floating point
local x = 10.0 + 20.0

-- Faster: Integer
local x = 10 + 20

Luau distinguishes between integers and floats internally. Integer operations are faster.

5. Minimize Function Call Overhead

-- Bad: Function call in tight loop
for i = 1, 1000000 do
    result = add(result, i)
end

-- Good: Inline the operation
for i = 1, 1000000 do
    result = result + i
end

6. Use rawget/rawset for Performance-Critical Access

-- With metamethod lookup
local value = table.key

-- Without metamethod lookup (faster)
local value = rawget(table, "key")

7. Pre-allocate Tables

-- Bad: Table grows dynamically
local t = {}
for i = 1, 1000000 do
    t[i] = i
end

-- Good: Pre-allocate
local t = table.create(1000000)
for i = 1, 1000000 do
    t[i] = i
end

8. Use task.defer for Non-Urgent Work

-- Spawn heavy work to run after current frame
task.defer(function()
    heavyComputation()
end)

-- Continue with urgent work
urgentWork()

9. Profile Your Code

--!profile

local function slowFunction()
    -- This will be profiled
end

Or use os.clock() for manual profiling:

local start = os.clock()
myFunction()
local elapsed = os.clock() - start
print(string.format("myFunction took %.6f seconds", elapsed))

10. Enable High-Resolution Timer (Windows)

For accurate profiling on Windows:

NICY_HIRES_TIMER=1 nicy run profile.luau

Benchmark Example

--!native
--!optimize 2

local function benchmark(name, fn, iterations)
    local start = os.clock()
    for i = 1, iterations do
        fn()
    end
    local elapsed = os.clock() - start
    print(string.format("%s: %.4f ms/op", name, elapsed / iterations * 1000))
end

-- Compare approaches
benchmark("global math.sin", function()
    math.sin(1.5)
end, 1000000)

local sin = math.sin
benchmark("local sin", function()
    sin(1.5)
end, 1000000)

See Also