首页 > 解决方案 > 通过使用本地函数优化 Lua 代码

问题描述

所以,我知道将全局函数分配给局部变量会使它们运行得更快,就像编写代码一样:

local _cos = math.cos
for i = 1, 100000 do
    _cos(i)
end

比没有首先本地化函数的代码快得多:

for i = 1, 100000 do
    math.cos(i)
end

但是,根据我的测试,似乎不适用于tonumber,typepairs.

有人可以澄清为什么一些全局函数变得更快,而其他函数似乎根本没有受到影响?

标签: lua

解决方案


本地化全局函数并不会显着提高它们的速度。它使它们更快一点,因为您不必在_ENV; 特别是如果他们在另一张桌子上,比如_ENV.math.cos. 对于直接在_ENV这个效果中的函数,显然更小,如果函数本身运行很慢,本地化的微小差异就不会那么明显。

事实上,你不应该仅仅因为本地化函数。如果您有一个非常小的循环体,其中有很多迭代调用了一个非常小的函数,那么您应该考虑对其进行本地化(并且您应该尽可能靠近循环执行此操作),但前提是您确定这将使差异(基准测试是您的朋友)。

似乎有一个长期存在的神话,即仅将您要使用的每个函数本地化到整个库就会神奇地使其更快,这完全是一种误解。

LuaJIT 甚至在大多数情况下自己都会这样做。检测循环体内重复的表访问并将其定位在循环外。

另请记住,虽然math.cos不应该更改,但您可能正在访问来自其他模块的函数,该函数实际上在幕后更改以反映模块中的某些状态更改。在这种情况下,本地化函数将意味着您正在使用过时的函数。这不是很常见,但确实会发生。


纯娱乐; 尝试在 PUC Lua 和 LuaJIT 中运行它:

local function bench(n, fn, ...)
    local t1 = os.clock()
    for i=1,n do
        fn(...)
    end
    local t2 = os.clock()
    return t2 - t1
end

local n = 1e7

print(bench(n, function() return math.cos(20) end))
print(bench(n, function() return tostring(20) end))
print(bench(n, function() return tonumber("20") end))
print("---------")
print(bench(n, math.cos, 20))
print(bench(n, tostring, 20))
print(bench(n, tonumber, "20"))

推荐阅读