Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过使用本地函数优化Lua代码_Lua - Fatal编程技术网

通过使用本地函数优化Lua代码

通过使用本地函数优化Lua代码,lua,Lua,因此,我知道将全局函数分配给局部变量会使它们运行得更快,就像编写代码一样: local _cos = math.cos for i = 1, 100000 do _cos(i) end 比不首先本地化函数的代码快得多: for i = 1, 100000 do math.cos(i) end 然而,根据我的测试,它似乎不适用于tonumber,type或pairs 有人能解释一下为什么一些全局函数变得更快,而另一些似乎根本没有受到影响吗?本地化全局函数并不能使它们更快。它使它

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

local _cos = math.cos
for i = 1, 100000 do
    _cos(i)
end
比不首先本地化函数的代码快得多:

for i = 1, 100000 do
    math.cos(i)
end
然而,根据我的测试,它似乎不适用于
tonumber
type
pairs


有人能解释一下为什么一些全局函数变得更快,而另一些似乎根本没有受到影响吗?

本地化全局函数并不能使它们更快。它使它们更快一些,因为您不必在
\u ENV
中查找它们;特别是如果它们位于另一个表中,如
\u ENV.math.cos
。对于直接位于
\u ENV
中的函数,这种影响显然较小,如果函数本身运行非常慢,那么将其本地化的微小差异就不会那么明显

事实上,您不应该仅仅因为以下原因而本地化函数。如果你有一个非常小的循环体,它有很多迭代,调用一个非常小的函数,那么你应该考虑本地化它(并且你应该尽可能地接近循环),但是只有当你确信这会有区别时(标杆是你的朋友)。 似乎存在这样一个长期存在的误区,即只需将要使用的每个函数本地化到整个库中,就会神奇地使其更快,这完全是一个误解

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

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


只是为了好玩;尝试在PUC Lua和LuaJIT中运行此命令:

本地功能台(n,fn,…)
本地t1=os.clock()
对于i=1,n do
fn(…)
结束
本地t2=操作系统时钟()
返回t2-t1
结束
本地n=1e7
打印(工作台(n,函数()返回数学cos(20)结束))
打印(工作台(n,函数()返回字符串(20)结束))
打印(工作台(n,函数()返回数字(“20”)结束))
打印(“-----------”)
打印(工作台(n,math.cos,20))
打印(工作台(n,tostring,20))
打印(台架(n,色调编号,“20”))

我所知道的唯一区别是,获取
tonumber
需要一个表访问(
\u ENV.tonumber
),而获取
cos
需要两个表访问(
\u ENV.math.cos
)。本地化
tonumber
真的一点速度都没有吗?正如您所说,这可能与表访问的数量有关。是的,当本地化
tonumber
时,速度没有提高,这也让我感到惊讶。我认为+30%是一个显著的性能提升。例如,我的测试以及Roberto Ierusalimschy的Lua性能提示(请参见:)表明,使用数学表中的函数可以显著提高性能。但是,您对直接位于
\u ENV
中的条目的解释可能不正确,这是有道理的。尽管如此,您不会从所有条目中获得+30%的增长;如果你的函数做了一些类似于连接数据库的事情,那么像函数本地化这样的小细节就会完全丢失。正如我所说的,基准测试确实是决定本地化内容的最佳方式,但只是毫无理由地这样做会使代码变得不必要的复杂。@DarkWiiPlayer-
毫无理由地这样做会使代码变得不必要的复杂
-你能对代码中的
本地时钟=os.clock
说同样的话吗?;-)可以说,对于
n=1e7
,是的,这有点不相关;但是为了保持代码的通用性,我试图避免循环结束后的双表查找,以使
t2
尽可能接近基准测试的实际结束;因此,基本上,每次我将控制流返回到调用代码时,我都在“使缓存失效”,以防
os.clock
在其他地方发生变化;D