Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring a value as local once is slower than declaring it local each time

How is it possible that this piece of code:

local t
for n = 0, 255 do
    t = math.random(0, 255)
    ...
end

Is actually slower than this one?

for n = 0, 255 do
    local t = math.random(0, 255)
    ...
end

Since I am accessing t more than once in the ... part, I am wondering, do for loops have their own set of local variables? If yes, is accessing a local variable from the current block faster than accessing one from the outer block?

like image 858
user6245072 Avatar asked May 19 '16 15:05

user6245072


1 Answers

In general, declare variables as local as possible. And yes, for loop makes its own scope. It's the better coding style, and, as this example shows, usually more optimized.

Let's see what instructions the two pieces of code are generating, with luac -l

The first piece:

main <t.lua:0,0> (13 instructions at 00000000005e8260)
0+ params, 8 slots, 1 upvalue, 5 locals, 5 constants, 0 functions
        1       [1]     LOADNIL         0 0
        2       [2]     LOADK           1 -1    ; 0
        3       [2]     LOADK           2 -2    ; 255
        4       [2]     LOADK           3 -3    ; 1
        5       [2]     FORPREP         1 6     ; to 12
        6       [3]     GETTABUP        5 0 -4  ; _ENV "math"
        7       [3]     GETTABLE        5 5 -5  ; "random"
        8       [3]     LOADK           6 -1    ; 0
        9       [3]     LOADK           7 -2    ; 255
        10      [3]     CALL            5 3 2
        11      [3]     MOVE            0 5
        12      [2]     FORLOOP         1 -7    ; to 6
        13      [4]     RETURN          0 1

The second piece:

main <t.lua:0,0> (11 instructions at 0000000000538260)
0+ params, 7 slots, 1 upvalue, 5 locals, 5 constants, 0 functions
        1       [1]     LOADK           0 -1    ; 0
        2       [1]     LOADK           1 -2    ; 255
        3       [1]     LOADK           2 -3    ; 1
        4       [1]     FORPREP         0 5     ; to 10
        5       [2]     GETTABUP        4 0 -4  ; _ENV "math"
        6       [2]     GETTABLE        4 4 -5  ; "random"
        7       [2]     LOADK           5 -1    ; 0
        8       [2]     LOADK           6 -2    ; 255
        9       [2]     CALL            4 3 2
        10      [1]     FORLOOP         0 -6    ; to 5
        11      [3]     RETURN          0 1

As you can see. The first piece has two extra instructions. One of them is inside the loop:

        11      [3]     MOVE            0 5

What this does is to move the result in the register 5 (which has the result of math.random, to the register 0 (which is where the variable t is). And that answers your question.

like image 86
Yu Hao Avatar answered Sep 18 '22 06:09

Yu Hao