If you don't mind, I have modified your source a bit for faster execution.
Of course I don't mind
I always avoid global variables, because this is a good programming style. Each chunk of code must "know" what it needs to know, and nothing else; therefore, using local variables is a must, otherwise you break the "data hiding", which is very dangerous.
... but strict data hiding has a price, because it brings an important restriction for flexibility and reusability
(Of course I'm against the use of "simple" global variables; I just wanted to add this little precision
)
However, each time a function is called, the interpreter must allocate memory for local variables, and deallocate that memory when exiting the function. So, using local variables is expected to increase execution time, especially if some functions are called several times (which is the rule, not the exception).
Well, not exactly... This is how it works in C language, but Lua (as most modern languages) works a bit differently. In fact it does not deallocate the local variables when exiting the function, but when the interpreter considers that it is the right time to do it; there is no individual deletion of each local variable at the end of the function. So memory deallocation isn't a problem here, however as you said memory allocation can slow down the execution speed.
It is really strange that you have experienced the opposite. Orwell, can you explain this?
It is difficult for me to give you a complete explanation, because I don't know exactly how the Lua interpreter works. And I must say it's not the first time I see such a surprising fact
Anyway, I think that I can give you some details about it.
The first thing is that he's not using local variables inside a function, but inside a chunk, so there is no repeted allocation process as PAP mentionned.
And the second thing comes from the way the interpreter looks for variables or functions. When the interpreter detects the use of a variable (or functions etc), it must find how it has been declared. It starts by browsing among the local variables, then it checks the global variables if it didn't find the reference yet. This is the correct behaviour, because local variables must "overload" the global variables with the same name without erasing it. So basically the access to global variables is a litte bit slower than to local variables.
(It may be a little more complicated, because the interpreter must deal with the different code environments etc, but the main principle is there).
I hope it answered to your question