Lua Performance Tips

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Xgoff
Party member
Posts: 211
Joined: Fri Nov 19, 2010 4:20 am

Re: Lua Performance Tips

Post by Xgoff »

T-Bone wrote:Is this true for love functions as well? Should you like do

Code: Select all

local print = love.graphics.print
and so on? I already do that with some functions, but only when I want to change them.
i'll usually just use something like

Code: Select all

local lg = love.graphics
not necessarily for optimization, but mainly because 'love.graphics' gets really annoying to type after a while. however, localizing is probably the easiest optimization you can do (one that can possibly increase readability), but it usually doesn't pay off as much unless you have a massive chain of table lookups or something. there's also the problem of having only 200 locals per function (for standard lua, but this might also apply to luajit as well), and sometimes you need some of those locals for other purposes like upvalues
ivan wrote:The biggest performance drop in Lua that I've noticed is from creating unnecessary tables (for example in a loop) that get destroyed right away.
i remember reading somewhere that table creation is actually quite expensive, even more expensive than creating closures. collection can be expensive since lua doesn't have a generational gc, so creating lots of temporary garbage (coughvectorscough) can be nasty. 5.2 apparently will have a generational gc but they never got feedback on it which... either means it will be removed or undocumented, probably
User avatar
benloran
Prole
Posts: 19
Joined: Tue Jul 05, 2011 4:52 pm

Re: Lua Performance Tips

Post by benloran »

ivan wrote: This is an extra assignment which is not present in the "localize_method_no" test.
Well, the point of test02 is to test whether it's worth localizing a method within the body of the loop (in the case that you can't localize it outside of that scope). If I move the localization out of the loop, then it's just a repeat of test01. To make it more fair, I guess I could put a throwaway assignment inside the loop in localize_method_no.
ivan wrote:
- Strangely, custom unpack function is slower than localized unpack.
I'm not that suprised since a custom unpack function would probably have to make more operations to the stack than the regular unpack. "unpack_custom" needs to start a function scope, look up values, push them on the stack, etc.
I guess I figured that unpack itself would need to do those things, too. I have no idea how unpack works under the hood.
ivan wrote:
- Do not use math.max, math.min. Use conditionals instead.
math.max can work with a variable number of arguments so I assume that's why it's slower in your test.
That's a good point. I think I'll add tests that compare a variable number of arguments as well.
ivan wrote: Test 8 probably also does an extra assignment (to a temp variable which is referenced to the "anonymous" function)
A more 'fair' test for funcparam_localized might be:

Code: Select all

         local func1 = function(a,b,func) return func(a+b) end

         local start = getTime()
         for n=1,cycles do
            local func2 = function(a) return a*2 end
            local x = func1(1,2,func2)
         end
I agree, I'll change that.

Thanks for the feedback!
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Lua Performance Tips

Post by Robin »

benloran wrote:I guess I figured that unpack itself would need to do those things, too. I have no idea how unpack works under the hood.
IIRC, unpack is implemented in C, so that would have the advantage of not needing to be interpreted. Lua's fast, but it's not machine code.
Help us help you: attach a .love.
User avatar
benloran
Prole
Posts: 19
Joined: Tue Jul 05, 2011 4:52 pm

Re: Lua Performance Tips

Post by benloran »

benloran wrote:
ivan wrote:
ivan wrote: Test 8 probably also does an extra assignment (to a temp variable which is referenced to the "anonymous" function)
A more 'fair' test for funcparam_localized might be:

Code: Select all

         local func1 = function(a,b,func) return func(a+b) end

         local start = getTime()
         for n=1,cycles do
            local func2 = function(a) return a*2 end
            local x = func1(1,2,func2)
         end
I agree, I'll change that.
Actually, I take it back. The original intent of test 8 (I believe... I copied this from the LuaPerformance site) was to show that it's better to localize an anonymous function outside of the loop than to just write an anonymous function inside the function call.

Robin wrote: IIRC, unpack is implemented in C, so that would have the advantage of not needing to be interpreted. Lua's fast, but it's not machine code.
That makes sense. I suspected something like that, but the same example on that LuaPerformance site shows the custom unpack as being much faster than Lua's unpack. That's what threw me.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Lua Performance Tips

Post by Robin »

benloran wrote:Actually, I take it back. The original intent of test 8 (I believe... I copied this from the LuaPerformance site) was to show that it's better to localize an anonymous function outside of the loop than to just write an anonymous function inside the function call.
Yeah, every time a function statement/expression is executed, a new closure is created.
Help us help you: attach a .love.
User avatar
Xgoff
Party member
Posts: 211
Joined: Fri Nov 19, 2010 4:20 am

Re: Lua Performance Tips

Post by Xgoff »

benloran wrote:
Robin wrote: IIRC, unpack is implemented in C, so that would have the advantage of not needing to be interpreted. Lua's fast, but it's not machine code.
That makes sense. I suspected something like that, but the same example on that LuaPerformance site shows the custom unpack as being much faster than Lua's unpack. That's what threw me.
the lua implementation of unpack is faster because... it's not actually the same thing as the builtin unpack

the c unpack has to loop through the provided table to get everything, while the lua implementation just uses a fixed set of direct table accesses; if you only need a certain number of values it will of course be cheaper to do it in lua, but if you need one capable of an arbitrary number of returns then your only choice is unpack. the lua <-> c overhead isn't insignificant either. however, a proper unpack implemented entirely in lua might be faster than the c version if you're using luajit
benloran wrote:Actually, I take it back. The original intent of test 8 (I believe... I copied this from the LuaPerformance site) was to show that it's better to localize an anonymous function outside of the loop than to just write an anonymous function inside the function call.
a nice thing 5.2 does is interning closures, if it detects that a function has the exact same definition and upvalues as another, it'll reuse the existing one instead of creating a new one. for example:

Code: Select all

-- in 5.1, 100 closures would be created; in 5.2 only 1 is
local x
for _ = 1, 100 do
    (function () return x end)()
end
it'll still be slower than defining the function outside of the loop/function/whereever, but not by a whole lot. on the other hand it's a lot slower in 5.1
User avatar
tsturzl
Party member
Posts: 161
Joined: Fri Apr 08, 2011 3:24 am

Re: Lua Performance Tips

Post by tsturzl »

Best advice I can give you for code optimization is do it once you're done, do it only in area's its needed, don't over do it, if you don't NEED it don't DO it. Though this advice conflicts heavily with the gamers mindset, where they buy quad-core processors and dual GPUs just to get better FPS in WoW, it doesn't really help you all that much. Seriously, optimization prematurely can kill your project. Optimization once your done, can just add bugs. If you don't NEED it don't DO it.
User avatar
miko
Party member
Posts: 410
Joined: Fri Nov 26, 2010 2:25 pm
Location: PL

Re: Lua Performance Tips

Post by miko »

Roland_Yonaba wrote:
T-Bone wrote:Is this true for love functions as well?
Of course, it is... Just assume that love functions are packed in a global table. Assigning them to local function make them run faster.
unless you have compiled love against luajit - in this case creating more variables makes things slower.
Roland_Yonaba wrote: Anyway, I am pretty sure that this is unecessary, cause Löve engine is fast enough. That would be superfluous...
Agree. And if you really want your code faster, use luajit version of love and don't mess with the source code. But then, 90% of the time spent is probably on SDL side, not on Lua side.
My lovely code lives at GitHub: http://github.com/miko/Love2d-samples
User avatar
GijsB
Party member
Posts: 380
Joined: Wed Jul 20, 2011 10:19 pm
Location: Netherlands

Re: Lua Performance Tips

Post by GijsB »

vrld,

when i did some changes to my code so it would get faster it was a diffrency of 0.1 seconds per frame :)
User avatar
slime
Solid Snayke
Posts: 3166
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Lua Performance Tips

Post by slime »

miko wrote:
Roland_Yonaba wrote:
T-Bone wrote:Is this true for love functions as well?
Of course, it is... Just assume that love functions are packed in a global table. Assigning them to local function make them run faster.
unless you have compiled love against luajit - in this case creating more variables makes things slower.
Incorrect. The only time localizing variables will hurt performance in LuaJIT is when localizing a function/variable in a FFI C library namespace directly. This only applies when you are using the LuaJIT FFI! localizing anything else will help performance!
Performance notice: the JIT compiler specializes to the identity of namespace objects and to the strings used to index it. This effectively turns function cdata objects into constants. It's not useful and actually counter-productive to explicitly cache these function objects, e.g. local strlen = ffi.C.strlen. OTOH it is useful to cache the namespace itself, e.g. local C = ffi.C.
Post Reply

Who is online

Users browsing this forum: lysandre, Semrush [Bot] and 7 guests