Good Practices
Codes good practices, pitfalls and tips
LUA
Gain performance: Early Return
You're probably used to coding like this:
local function myMethod()
if condition then
-- do a little dance, make a little loveโฆ
end
end
In LUA, you can skim a few processing cycles by using the early return style:
local function myMethod()
if not condition then return end
-- do a little dance, make a little loveโฆ
end
You can gain a significant amount of performance this way, especially when doing this in a loop.
Fixing/preventing nil access
LUA throws an exception if it encounters nil
in unexpected places. The corresponding error will look like this:
attempt to access local '<variable name>' (a nil value)
stack traceback:
my_example.lua:1234 in function 'MyFunctionName
Open the corresponding file, find the correct line, and check what is being accessed there. It will look like variable.property
, or perhaps something will be concatenated to a string ("something something text" .. variable
).
You can assign a default value to the property in question:
myString = <original string assignment> or ""
myNumber = <original number assignment> or 0
myEverythingElse = <original object assignment> or {}
Switch in LUA: Lookup Tables
Who doesn't know the problem? You want to know if your string is A, B, or C, but not D โ and LUA doesn't have a switch statement.
Fortunately, there is a built-in and performant way to
Performance killers: strings
String concatenation and comparison can be the difference between a brief stutter and a complete freeze or even crash to desktop. This is not a joke โ see here for more detail.
Comparing/Searching
Lua internalizes strings. That means these two strings will share a single representation in memory:
local string1 = "This is the same object!"
local string2 = "This is the same object!"
The comparison between those two strings will be almost-instant.
This becomes a problem when comparing strings in a loop (see Scopes):
for (_, mystring) in ipairs(mytable) do
if mystring == "This is the same object!" then
-- do something
end
end
Every single pass of the loop will create a memory representation of "This is the same object!" and then discard it again.
local myCompareString = "This is the same object!"
for (_, mystring) in ipairs(mytable) do
if mystring == myCompareString then
-- do something
end
end
Takeaway:
If at all possible, define things outside the scope of loops!
Finding in strings
Lua's regex implementation is very limited. There is a limitation for pipes. For example, the following example will actually iterate twice after creating internal string representations:
if string.find("catastrophe", "dog|cat") then
-- do something
end
It is faster to just do this:
if string.find("catastrophe", "dog") or string.find("catastrophe", "cat") then
-- do something
end
On top of that, string.match
will return the entire string if no match is found:
local match = string.match("catastrophe", "dog")
if match ~= "catastrophe" then
-- do something
end
The alternative:
if string.find("catastrophe", "dog")
-- do something
end
Takeaway:
Avoid regex
prefer
String.find()
overString.match()
Concatenation
Scopes
Don't do this (30% less performant):
function foo(x)
for i = 1, 1000000 do
x = x + math.sin(i)
end
return x
end
Do this instead:
local sin = math.sin
function foo(x)
for i = 1, 1000000 do
x = x + sin(i)
end
return x
end
Last updated