为什么局部变量的访问速度比lua中的全局变量快?

Jdc*_*197 14 lua global-variables local-variables

所以我正在阅读Lua 2nd Ed中的编程,我在这里看到了这一段:

尽可能使用局部变量是一种很好的编程风格.局部变量可帮助您避免使用不必要的名称来混淆全局环境.此外,对局部变量的访问比对全局变量的访问更快.

谁能解释为什么会这样?这个"功能"仅在Lua中,还是在其他语言中?(例如C,C++,Java)

ant*_*kos 11

运行时间的差异是由于哈希表查找和数组查找之间的差异.解释器可能能够将局部变量放在CPU寄存器中,但即使没有这种聪明,局部变量也可以更快地访问.

Lua中的全局变量存储在表中.通常,任何人都可以修改这些表,因此解释器必须在每次访问时重新查找值.另一方面,局部变量只有在超出范围时才会消失.因此,它们可以在阵列中具有固定位置.

下面的基准程序在循环中调用虚函数.基准测试显示了程序必须跳过的表格越多,运行时间越长.

其他动态语言应该具有类似的特征; 例如,在最后看到Python基准测试.

一些相关链接:

档案demo.lua:

local M = {}
_G.demo = M
function M.op(x) return x end
return M
Run Code Online (Sandbox Code Playgroud)

档案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)
Run Code Online (Sandbox Code Playgroud)

档案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)
Run Code Online (Sandbox Code Playgroud)


oni*_*nit 8

在任何语言中,局部变量都会更快.您将需要了解寄存器是什么以及线程堆栈是什么来理解我的解释.大多数局部变量都是作为寄存器变量实现的,或者是在本地堆栈顶部附近推送的,因此通常可以更快地访问它们.全局变量存储在堆栈的更高位置(如果它们不在堆上),因此计算它们访问它们的地址会变慢.

我在这里做了一些关于Lua内部工作的假设,但从计算机架构的角度来看这是有道理的.

  • @ Jdc1197:它是一种混合寄存器/堆栈的东西.它有一个堆栈,但它的大部分功能都可以修改不在堆栈顶部的东西.因此,堆栈实际上只是一个可增长的寄存器文件. (2认同)