【问题标题】:Is putting a function inside another function in lua would provide a performence boost in lua?将一个函数放在 lua 中的另一个函数中会提高 lua 的性能吗?
【发布时间】:2020-07-05 14:32:57
【问题描述】:

如果我将一个函数放在另一个函数中,以便在我们在函数内部添加的函数中调用它,如下例所示:

local function readInputFromUser() 
    local doSum()
        print("Give me a number")
        return io.read("n")
    end
    num1 = doSum()
    num2 = doSum()
    print("The sum of " num1 .. " and " .. num2 .. " is equaling " num1 + num2)
end

与调用像以下示例一样启动的函数相比,它会给我的程序带来性能提升吗:

local doSum()
    print("Give me a number")
    return io.read("n")
end

local function readInputFromUser() 
    num1 = doSum()
    num2 = doSum()
    print("The sum of " num1 .. " and " .. num2 .. " is " num1 + num2)
end

将第二个示例中的 doSum() 函数作为全局函数用于性能是否也有好处?

【问题讨论】:

  • 第二种变体更快。
  • @EgorSkriptunoff 如果我将函数分成两个作为全局变量会更快吗?
  • 不,局部变量比全局变量快
  • 该代码不是有效的 Lua 代码。写local function doSum()

标签: function lua


【解决方案1】:

当您将一个函数放入另一个函数中时,编译后的代码不会创建一次并每次都重新使用它。

看一下第一个代码的LuaJIT字节码:

这是doSum函数的字节码:

0001    GGET     0   0      ; "print"
0002    KSTR     1   1      ; "Give me a number"
0003    CALL     0   1   2
0004    GGET     0   2      ; "io"
0005    TGETS    0   0   3  ; "read"
0006    KSTR     1   4      ; "n"
0007    CALLT    0   2

这是readInputFromUser函数的开始:

0001    FNEW     0   0
0002    MOV      1   0
0003    CALL     1   2   1
...
...
...

看看第一条指令:

0001 FNEW 0 0

FNEW 表示Create new closure from prototype D and store it in A

这个指令会在你每次运行readInputFromUser时创建一个新的闭包(闭包是函数中的函数)。 闭包的创建包含几个过程。 它为新函数分配空间、添加到 GC 列表、添加上值、局部变量等等。

这会消耗 CPU 时间,也会破坏 JIT 编译。 (在普通 Lua 中,闭包的 CPU 时间更长)

您的函数 doSum 不使用来自 readInputFromUser 的任何值,因此您可以做的是在 readInputFromUser 之外创建 doSum 并将其用作上值(Upvalue 是外部(及以上)的局部变量功能)。 Upvalues 比本地人花费更多,但创建闭包的成本比 upvalue 高得多,所以在这里使用 upvalue 是可以的。 您可以通过将 doSum 设为全局来避免这种升值,但全局的成本会更高一些 (locals > upvalues > globals > closures)。

Sum:创建闭包代价高昂,如果您的函数不使用 upvalues,您可以在外部创建一次并重复使用。

顺便说一句,您在最后一个 printdoSum 定义中有语法错误。 此外,这是第一个代码和第二个代码之间的近似基准测试:

doSum inside readInputFromUser: 0.29265 (Min: 0.27215, Max: 0.35823, Average: 0.29573) second(s) (81816.93%) (818 times slower)
doSum as upvalue: 0.00036 (Min: 0.0003, Max: 0.00108, Average: 0.00042) second(s) (100%)

【讨论】:

    猜你喜欢
    • 2015-07-14
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 2015-12-17
    • 2012-02-06
    • 2011-01-29
    • 1970-01-01
    • 2011-08-29
    相关资源
    最近更新 更多