为什么在Lua中,访问局部变量比全局变量更快?

15

我正在阅读《Lua程序设计(第2版)》,看到下面这段话:

在编程时尽可能使用本地变量是良好的编程风格。本地变量有助于避免将不必要的名称杂乱无章地添加到全局环境中。此外,访问本地变量比访问全局变量更快

有人能解释一下为什么吗?这个“特性”只存在于Lua中,还是其他语言也有呢?(例如C、C ++、Java)


1
一些有关C++访问速度的讨论 - https://dev59.com/ruo6XIcBkEYKwwoYSChJ 我猜在其他编程语言中也会存在类似的问题,尽管我在这个领域不是专家。 - Dan Blows
我认为这可能会有所帮助。我相信这个想法是与语言无关的: https://dev59.com/Sp3ha4cB1Zd3GeqPTFss#41148360 - Kyle
我认为这可能会有所帮助。我相信这是一种与语言无关的想法:https://dev59.com/Sp3ha4cB1Zd3GeqPTFss#41148360 - Kyle
2个回答

11
运行时间的差异是由哈希表查找和数组查找之间的差异引起的。解释器可能能够将局部变量放置在 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)

8
在任何语言中,局部变量都会更快。您需要了解register是什么,以及线程stack是什么,才能理解我的解释。大多数局部变量被实现为寄存器变量或推到本地堆栈的顶部附近,因此它们通常可以更快地访问。全局变量存储在堆栈的更高位置(如果它们不在堆上),因此计算其地址以访问它们会更慢。
我在这里对Lua的内部工作做出了一些假设,但从计算机体系结构的角度来看,这是有道理的。

是的,我认为Lua实际上在寄存器为基础的虚拟机上运行,所以这很有道理。 - Jdc1197
2
@Jdc1197:它有点像混合寄存器/堆栈的东西。它有一个堆栈,但大多数功能可以修改不在堆栈顶部的内容。因此,堆栈实际上只是一个可扩展的寄存器文件。 - Nicol Bolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接