The difference in running time is due to the difference between hash table lookup and array lookup. An interpreter might be able to place a local variable in a CPU register, but even without such cleverness local variables are faster to access.
Global variables in Lua are stored in tables. Generally, anyone can modify these tables, and therefore the interpreter has to lookup a value anew every time it is being accessed. Local variables on the other hand disappear only when they go out of scope. Therefore they can have fixed locations in an array.
The benchmark program below calls a dummy function in a loop. The benchmark shows how the running time goes up the more tables the program has to jump through.
Other dynamic languages should be expected to have similar characteristics; see for example the Python benchmark at the very end.
Some relevant links:
File demo.lua
:
local M = {}
_G.demo = M
function M.op(x) return x end
return M
File main.lua
:
local M = require "demo"
op = demo.op
local outer_op = demo.op
function iter_op(n)
local inner_op = demo.op
for i = 1, n do
-- Example running times for n = 100,000,000 (Lua 5.2.0):
-- Lookup a table (demo or _G), then lookup 'op'
-- within that table:
--
-- demo.op(i) --> 0:40
-- _G.op(i) --> 0:39
-- Lookup 'op' within a known local table (M or the table of
-- globals):
--
-- M.op(i) --> 0:30
-- op(i) --> 0:30
-- Dereference a local variable declared inside or outside
-- of this iter_op() function:
--
-- inner_op(i) --> 0:23
-- outer_op(i) --> 0:22
end
end
iter_op(100000000)
File main.py
:
import demo # Contains 'def op(x): return x'.
global_op = demo.op
def iter_op(n):
local_op = demo.op
for i in xrange(n):
# Example running times for n = 50,000,000 (Python 2.6.5):
# demo.op(i) # 0:50
# global_op(i) # 0:41
local_op(i) # 0:36
iter_op(50000000)