我正在 LuaJIT 中工作,并将所有库和其他内容存储在“foo”中,如下所示:
foo = {}; -- The only global variable
foo.print = {};
foo.print.say = function(msg) print(msg) end;
foo.print.say("test")
现在我想知道,使用元表并将所有库保留在本地是否有帮助?或者说没关系。我想到的是这样的:
foo = {};
local libraries = {};
setmetatable(foo, {
__index = function(t, key)
return libraries[key];
end
});
-- A function to create a new library.
function foo.NewLibrary(name)
libraries[name] = {};
return libraries[name];
end;
local printLib = foo.NewLibrary("print");
printLib.say = function(msg) print(msg) end;
-- Other file:
foo.print.say("test")
我现在确实没有工具来对此进行基准测试,但是将库的实际内容保留在本地表中是否会提高性能?哪怕是最轻微的?
我希望我已经说清楚了这一点,基本上我想知道的是:性能方面第二种方法更好吗?
如果有人可以链接/给出有关 Lua 中如何处理全局变量的详细解释,这也可以解释这一点,那就太好了。
最佳答案
don't really have the tools to benchmark this right now
当然可以。
local start = os.clock()
for i=1,100000 do -- adjust iterations to taste
-- the thing you want to test
end
print(os.clock() - start)
对于性能,您几乎总是想要进行基准测试。
would keeping the actual contents of the libraries in a local table increase performance at all?
与第一个版本的代码相比?理论上不会。
您的第一个示例(剔除不必要的多余内容):
foo = {}
foo.print = {}
function foo.print.say(msg)
print(msg)
end
要获得打印功能,需要进行三个表查找:
- 索引 _ENV 为“foo”
- 使用“print”索引
foo
表 - 使用“say”索引
foo.print
表。
你的第二个例子:
local libraries = {}
libraries.print = {}
function libraries.print.say(msg)
print(msg)
end
foo = {}
setmetatable(foo, {
__index = function(t, key)
return libraries[key];
end
});
要实现打印功能,现在需要进行五次表查找以及其他额外工作:
- 索引 _ENV 为“foo”
- 使用“print”索引
foo
表 - Lua 发现结果为 nil,检查
foo
是否有元表,找到一个 - 使用“__index”索引元表
- 检查结果是表还是函数,Lua 发现它是一个函数,所以用 key 调用它
- 使用“print”索引
库
- 使用“say”为
print
表建立索引
其中一些额外工作是在 C 代码中完成的,因此比全部在 Lua 中实现要快,但肯定会花费更多时间。
使用我上面展示的循环进行基准测试,第一个版本的速度大约是普通 Lua 中第二个版本的两倍。在LuaJIT中,两者的速度完全相同。显然,差异在 LuaJIT 中的运行时得到了优化(这非常令人印象深刻)。只是为了展示基准测试的重要性。
旁注:Lua 允许您为 __index
提供一个表,这将导致与您的代码等效的查找:
setmetatable(foo, { __index = function(t, key) return libraries[key] end } )
所以你可以写:
setmetatable(foo, { __index = libraries })
这也恰好快得多。
关于lua - 全局变量很糟糕,这会以任何方式提高性能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14881331/