Performance Optimization in Lua
Writing fast, efficient code is crucial for performance-critical applications. In this final lesson, you'll learn how to profile your Lua code, identify bottlenecks, and apply optimization techniques. Let's explore performance optimization in Lua!
Profiling Your Code
Simple Timing
local function benchmark(func, iterations)
iterations = iterations or 1000000
local start = os.clock()
for i = 1, iterations do
func()
end
local finish = os.clock()
local elapsed = finish - start
print(string.format("Time: %.6f seconds", elapsed))
print(string.format("Per iteration: %.9f seconds", elapsed / iterations))
end
-- Usage
benchmark(function()
local x = 10 * 20
end)
Profiler Function
local Profiler = {}
function Profiler:new()
local self = {
times = {},
counts = {}
}
setmetatable(self, {__index = Profiler})
return self
end
function Profiler:start(name)
self.times[name] = os.clock()
end
function Profiler:stop(name)
if not self.times[name] then return end
local elapsed = os.clock() - self.times[name]
self.counts[name] = (self.counts[name] or 0) + 1
self.times[name] = (self.times[name] or 0) + elapsed
end
function Profiler:report()
print("\n=== Profiler Report ===")
for name, time in pairs(self.times) do
local count = self.counts[name]
print(string.format("%s: %.6fs (%d calls, %.9fs avg)",
name, time, count, time / count))
end
end
-- Usage
local prof = Profiler:new()
prof:start("calculation")
-- Do work
prof:stop("calculation")
prof:report()
Click Run to execute your code
Optimization Techniques
1. Use Local Variables
-- Slow: Global lookups
function slow()
for i = 1, 1000000 do
local x = math.sin(i)
end
end
-- Fast: Local cache
function fast()
local sin = math.sin
for i = 1, 1000000 do
local x = sin(i)
end
end
2. Avoid table.insert() in Loops
-- Slower
local function buildArray1(n)
local arr = {}
for i = 1, n do
table.insert(arr, i)
end
return arr
end
-- Faster: Direct assignment
local function buildArray2(n)
local arr = {}
for i = 1, n do
arr[i] = i
end
return arr
end
3. Use table.concat() for Strings
-- Slow: String concatenation
local function buildString1(n)
local s = ""
for i = 1, n do
s = s .. tostring(i)
end
return s
end
-- Fast: table.concat()
local function buildString2(n)
local parts = {}
for i = 1, n do
parts[i] = tostring(i)
end
return table.concat(parts)
end
4. Reuse Tables
-- Slow: Create new table each iteration
for i = 1, 10000 do
local temp = {}
temp.x = i
temp.y = i * 2
-- Use temp
end
-- Fast: Reuse table
local temp = {}
for i = 1, 10000 do
temp.x = i
temp.y = i * 2
-- Use temp
end
Click Run to execute your code
Memory Management
Garbage Collection
-- Check memory usage
local function getMemoryUsage()
return collectgarbage("count")
end
print("Memory:", getMemoryUsage(), "KB")
-- Force garbage collection
collectgarbage("collect")
-- Set GC parameters
collectgarbage("setpause", 100) -- Pause between collections
collectgarbage("setstepmul", 200) -- GC step multiplier
Weak Tables
-- Weak table for caching
local cache = {}
setmetatable(cache, {__mode = "v"}) -- Weak values
function getCachedValue(key)
if not cache[key] then
cache[key] = expensiveComputation(key)
end
return cache[key]
end
Algorithm Optimization
Memoization
-- Slow: Recursive fibonacci
local function fib1(n)
if n <= 1 then return n end
return fib1(n - 1) + fib1(n - 2)
end
-- Fast: Memoized fibonacci
local function memoize(func)
local cache = {}
return function(n)
if not cache[n] then
cache[n] = func(n)
end
return cache[n]
end
end
local fib2
fib2 = memoize(function(n)
if n <= 1 then return n end
return fib2(n - 1) + fib2(n - 2)
end)
print(fib2(30)) -- Much faster!
Early Exit
-- Slow: Check all items
local function findItem1(items, target)
local found = false
for i, item in ipairs(items) do
if item == target then
found = true
end
end
return found
end
-- Fast: Early exit
local function findItem2(items, target)
for i, item in ipairs(items) do
if item == target then
return true
end
end
return false
end
Click Run to execute your code
Common Performance Pitfalls
- Global variables: Slower than local
- Repeated table lookups: Cache in locals
- String concatenation in loops: Use table.concat()
- Creating tables in loops: Reuse when possible
- Unnecessary function calls: Inline simple operations
- Premature optimization: Profile first!
Performance Best Practices
- Profile before optimizing: Find real bottlenecks
- Use local variables: Faster than globals
- Cache table lookups: Especially in loops
- Choose right data structures: Arrays vs hash tables
- Avoid unnecessary allocations: Reuse tables
- Use appropriate algorithms: O(n) vs O(nยฒ)
- Lazy evaluation: Compute only when needed
- Batch operations: Reduce overhead
Before and After Optimization
Before: Slow Code
function processData(data)
local result = ""
for i = 1, #data do
result = result .. tostring(data[i])
if math.sqrt(data[i]) > 10 then
result = result .. " (large)"
end
end
return result
end
After: Optimized Code
function processData(data)
local parts = {}
local sqrt = math.sqrt
local tostring = tostring
local n = #data
for i = 1, n do
local value = data[i]
parts[#parts + 1] = tostring(value)
if sqrt(value) > 10 then
parts[#parts + 1] = " (large)"
end
end
return table.concat(parts)
end
Improvements:
- Use table.concat() instead of string concatenation
- Cache math.sqrt and tostring in locals
- Cache #data outside loop
- Use direct array assignment
Practice Exercise
Optimize this code:
Click Run to execute your code
Summary
In this lesson, you learned:
- Profiling code with timing and profiler functions
- Optimization techniques (local variables, table operations)
- Memory management and garbage collection
- Algorithm optimization (memoization, early exit)
- Common performance pitfalls to avoid
- Performance best practices
- Before/after optimization examples
๐ Congratulations!
You've completed the Lua tutorial!
You've learned everything from basic syntax to advanced topics like coroutines, OOP, modules, error handling, and performance optimization. You now have the skills to build robust, efficient Lua applications.
What's next?
- Build real projects to practice your skills
- Explore Lua frameworks (LรVE for games, OpenResty for web)
- Contribute to open-source Lua projects
- Dive deeper into LuaJIT for maximum performance
- Learn C API for extending Lua
Keep coding and happy Lua programming! ๐
Enjoying these tutorials?