user12136376
user12136376

Reputation:

Is putting a function inside another function in lua would provide a performence boost in lua?

If I put a function in another function to call it in the function that we added inside the function like in the following example:

local function readInputFromUser() 
    local doSum()
        print("Give me a number")
        return io.read("n")
    end
    num1 = doSum()
    num2 = doSum()
    print("The sum of " num1 .. " and " .. num2 .. " is equaling " num1 + num2)
end

Would it give my program an performance boost compared to calling to a function initiated like the following example:

local doSum()
    print("Give me a number")
    return io.read("n")
end

local function readInputFromUser() 
    num1 = doSum()
    num2 = doSum()
    print("The sum of " num1 .. " and " .. num2 .. " is " num1 + num2)
end

Would it also beneficial to put the doSum() function in the second example as a global function for performence?

Upvotes: 1

Views: 542

Answers (1)

Spar
Spar

Reputation: 1762

When you put a function inside another function the compiled code doesn't create it once and re-use it each time.

Take a look at LuaJIT bytecode of the first code:

This is bytecode of doSum function:

0001    GGET     0   0      ; "print"
0002    KSTR     1   1      ; "Give me a number"
0003    CALL     0   1   2
0004    GGET     0   2      ; "io"
0005    TGETS    0   0   3  ; "read"
0006    KSTR     1   4      ; "n"
0007    CALLT    0   2

This is the start of readInputFromUser function:

0001    FNEW     0   0
0002    MOV      1   0
0003    CALL     1   2   1
...
...
...

Take a look at the first instruction:

0001 FNEW 0 0

FNEW means Create new closure from prototype D and store it in A.

This instruction will create a new closure each time you run readInputFromUser (Closure is a function inside a function). The creation of a closure contains several procedures. It allocates the space for the new function, adds to GC list, adds upvalues, locals and many more things.

This costs CPU time, also this breaks JIT compilation. (In plain Lua the CPU time for closures is bigger)

Your function doSum doesn't use any values from readInputFromUser, so what you can do instead is create doSum outside readInputFromUser and use it as upvalue (Upvalue is a local variable outside (and above) the function). Upvalues cost more that locals, but closure creation costs much more than upvalue, so that's ok to use upvalue here. You can avoid this upvalue by making doSum global, but globals cost a little bit more (locals > upvalues > globals > closures).

Sum: Creating a closure is expensive, if your function doesn't use upvalues, you can create it once outside and re-use.

Btw, you have syntax errors in the last print and in doSum definition. Also, this is approximate benchmark test between first code and the second:

doSum inside readInputFromUser: 0.29265 (Min: 0.27215, Max: 0.35823, Average: 0.29573) second(s) (81816.93%) (818 times slower)
doSum as upvalue: 0.00036 (Min: 0.0003, Max: 0.00108, Average: 0.00042) second(s) (100%)

Upvotes: 1

Related Questions