Ответ 1
Разница во времени выполнения связана с различием между поиском таблицы хэшей и поиском массива. Интерпретатор может разместить локальную переменную в регистре CPU, но даже без такой умности локальные переменные быстрее доступны.
Глобальные переменные в Lua хранятся в таблицах. Как правило, каждый может изменять эти таблицы, и поэтому интерпретатор должен искать значение заново каждый раз, когда к нему обращаются. Локальные переменные, с другой стороны, исчезают только тогда, когда они выходят за рамки. Поэтому они могут иметь фиксированные местоположения в массиве.
В приведенной ниже тестовой программе вызывается фиктивная функция в цикле. Тест показывает, как время работы увеличивается, чем больше таблиц, которые программа должна выполнить.
Ожидается, что другие динамические языки будут иметь схожие характеристики; см., например, тест Python в самом конце.
Некоторые релевантные ссылки:
- Оптимизация использования локальных переменных (Lua)
- Локальные переменные (советы по производительности Python)
- Оптимизация доступа к глобальной переменной/доступу. A (отозванное) предложение Python по поиску глобальных и локальных объектов.
Файл demo.lua
:
local M = {}
_G.demo = M
function M.op(x) return x end
return M
Файл 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)
Файл 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)