Почему локальные переменные доступны быстрее, чем глобальные переменные в lua?

Итак, я читал Программирование в Lua 2nd Ed, и я наткнулся на этот параграф здесь:

Хороший стиль программирования позволяет использовать локальные переменные всякий раз возможное. Локальные переменные помогают избежать загромождения глобальных с ненужными именами. Кроме того, доступ к локальным переменные быстрее, чем глобальные.

Может ли кто-нибудь объяснить, почему это так? И эта "особенность" есть только в Lua, или это также на других языках? (например, C, С++, Java)

Ответы

Ответ 1

Разница во времени выполнения связана с различием между поиском таблицы хэшей и поиском массива. Интерпретатор может разместить локальную переменную в регистре CPU, но даже без такой умности локальные переменные быстрее доступны.

Глобальные переменные в Lua хранятся в таблицах. Как правило, каждый может изменять эти таблицы, и поэтому интерпретатор должен искать значение заново каждый раз, когда к нему обращаются. Локальные переменные, с другой стороны, исчезают только тогда, когда они выходят за рамки. Поэтому они могут иметь фиксированные местоположения в массиве.

В приведенной ниже тестовой программе вызывается фиктивная функция в цикле. Тест показывает, как время работы увеличивается, чем больше таблиц, которые программа должна выполнить.

Ожидается, что другие динамические языки будут иметь схожие характеристики; см., например, тест 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)

Ответ 2

В любом языке локальные переменные будут быстрее. Вам нужно будет понять, что такое register и что поток stack - это понять мои объяснения. Большинство локальных переменных реализованы как регистровая переменная или приближаются к вершине локального стека, поэтому к ним обычно обращаются гораздо быстрее. Глобальные переменные хранятся дальше по стеку (если они не находятся в куче), поэтому вычисление их адреса для доступа к ним происходит медленнее.

Я делаю некоторые предположения здесь о внутренней работе Lua, но это имеет смысл с точки зрения компьютерной архитектуры.