I've got a couple advices about optimization.
Avoid premature optimization. This one is not mine:
Donald Knut wrote:We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil
The best way of having a correct algorithm is:
- Start with code as human-understandable as possible. In some occasions this will mean making your code slightly slower on the CPU, but if it makes your code easier to understand for the programmer, then it is the right way to go.
- Then, if your code is fast enough (90% of the time it is), you have finished. You won. Go do another thing.
- If it is too slow for your needs, *profile it*. Don't start making random "optimizations" here and there. Be methodical, and find the real bottlenecks.
- When you have found where the real performance issue is, optimize that part only. This could render the code a little less understandable for humans. Add as many comments as necessary in order to compensate that.
This is also
not mine.
I want to point out that I don't want to imply that optimized code is allways "more complex" than non-optimized code. Quite often it is just the opposite; the fastest solution is also the simplest to understand. Trying to achieve the most optimized code isn't about thinking about "details" (how can I initialize this variable faster? How can I increase this other faster?) but about the whole structure of your progam (do I really need to cycle over this bunch of elements? Can I save this to a variable instead of having to calculate it on every frame?)
Now, for some lua-specifics:
- The __index metamethod invokation is quite fast (3 pointer indirections in C, if I remember correctly). Use it when you can, but remember: make your code human-understandable.
- This is implementation-specific, but in general, ipairs(t) is a bit faster than pairs(t)
- Tables with non-consecutive integers, or with 'gaps', are less efficient than tables without gaps (ipairs stops at the first gap, so you have to use pairs to parse them)
- There's also the common idiom for the ternary operator. In other languages you have a ternary operator using ? and : :
Since in LUA there are no ternary operators, you have to use if-elses to do the same thing:
But there's actually a more efficient way of doing the same thing in lua using and-or :
This code does the same as the previous one, but it is faster. Since it is not very human-readable, add a comment:
Code: Select all
-- if b > 0, then a=1. Else a = 0
a = b > c and 1 or 0
Also, this solution only works for small conditions, such as b>c. For more complex conditions, it is better that you use an if.
- Another place for skipping ifs is in the default parameters of functions. If you have a function with an optional parameter, and you want it to be 1 by default, use 'or' like this:
Code: Select all
function foo(p1, p2) -- p2 is optional, default value of 1
p2 = p2 or 1 -- if p2 is nil, this sets it to 1. Otherwise it leaves it untouched