本地声明的 lua 函数是不是在每次传递时都会被解析?

Posted

技术标签:

【中文标题】本地声明的 lua 函数是不是在每次传递时都会被解析?【英文标题】:Do locally declared lua functions get parsed every time they are passed?本地声明的 lua 函数是否在每次传递时都会被解析? 【发布时间】:2021-10-11 18:47:33 【问题描述】:

假设我在另一个经常被调用的函数中有一个本地声明的函数:

function outer()
    -- Do stuff
    local loop = true
    while loop do -- for some reason
        local function inner()
            -- Do function stuff
        end
        -- Doing stuff
        inner()
    end
end

每次在运行时遇到内部函数时,是否都会重新创建、解析、处理所有内容?基本上,这种模式和声明单独的独立函数之间有什么性能差异吗?

function inner()
    -- Do stuff
end

functions outer()
    local loop = true
    while loop do
        inner()
    end
end

【问题讨论】:

【参考方案1】:

简短回答:不。

当你运行一个 Lua 块(一个块通常是一个文件,但有时是一个字符串)时,整个块在执行之前被编译成字节码。当您定义一个本地函数时,您正在将对该函数的字节码的引用分配给该函数的名称。 Lua 不会重新评估函数本身。

在您的第一个代码 sn-p 中,您可能会因将字节码引用分配给局部变量而受到轻微的性能损失。当然,您应该确定这一点。不知道 Lua 能不能把它优化掉。

请注意,闭包可以有不同的上值集,但仍然引用相同的函数字节码。

【讨论】:

【参考方案2】:

除了 luther 提供的答案之外,还有更多内容,但您可能想知道它是否重要。我认为这对性能影响不大。

Lua 将编译每个功能块,但是当您使用本地函数时,每次调用特定代码时都必须执行 CLOSURE 指令和 MOVE 指令。添加 MOVE 是为了防止 CALL 指令将闭包弹出堆栈。我不相信 Lua 在任何情况下都优化了这一点。

如果您有一个全局函数或一个上值,它只需要使用 GETGLOBAL、GETTABUP 或 GETUPVALUE 指令来获取该值。

你可以在这里看到生成的字节码; https://luac.nl/s/473abd2a0bb427a31766ea917

【讨论】:

以上是关于本地声明的 lua 函数是不是在每次传递时都会被解析?的主要内容,如果未能解决你的问题,请参考以下文章

每次调用 Func 时都会重写 UIView

每次设置状态时都会调用 Flutter 函数

javascript原型和内存[重复]

Rails 脚手架 scss 每次生成脚手架时都会重置

Angular2,为啥每次移动鼠标时都会调用函数

SWIG:Lua - 将 c++ 实例作为 lua 函数参数传递