全局变量是不好的,这会以任何方式提高性能吗?

我正在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中如何处理全局变量的详细说明,那就太好了。

点赞
用户501459
用户501459

现在并没有真正的工具来测试这个

你确实有。

local start = os.clock()
for i=1,100000 do -- 调整迭代次数以适应情况
    -- 要测试的内容
end
print(os.clock() - start)

在性能方面,你几乎总是需要进行基准测试。

保留库的实际内容是否会提高性能?

与代码的第一个版本相比?从理论上讲不会。

你的第一个例子(去掉不必要的麻烦):

foo = {}
foo.print = {}
function foo.print.say(msg)
    print(msg)
end

要调用你的打印函数需要三个表查找:

  1. 用 "foo" 索引 _ENV
  2. 使用 "print" 索引 foo
  3. 使用 "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
});

现在要调用你的打印函数需要五个表查找和其他额外的工作:

  1. 使用 "foo" 索引 _ENV
  2. 使用 "print" 索引 foo
  3. Lua 发现结果为 nil,检查 foo 是否有一个元表,发现有一个
  4. 使用 "__index" 索引元表
  5. 检查结果是否是表或函数,Lua 发现它是一个函数,因此调用它并传递关键字
  6. 使用 "libraries" 索引 libraries
  7. 使用 "say" 索引print

其中一些额外的工作是在 C 代码中完成的,因此它比如果所有内容都在 Lua 中实现要快,但肯定需要更多时间。

使用我上面展示的循环进行基准测试,第一个版本在普通的 Lua 中大约是第二个版本的两倍。在 LuaJIT 中,两者的速度完全相同。显然,LuaJIT 在运行时优化了差异(这相当令人印象深刻)。这只是说明了基准测试的重要性。


附注:Lua 允许您提供一个表作为“_ _ index”,这将导致与您的代码等效的查找:

setmetatable(foo, { __index = function(t, key) return libraries[key] end } )

因此,您可以编写:

setmetatable(foo, { __index = libraries })

这也恰巧更快。

2013-02-14 20:07:58
用户646619
用户646619

以下是我编写模块的方式:

-- foo.lua
local MyLib = {}

function MyLib.foo()
    ...
end

return MyLib

-- bar.lua
local MyLib = require("foo.lua")
MyLib.foo()

请注意,return MyLib 不在一个函数中。require 捕捉这个返回值并将其用作库。这样,就没有全局变量了。

2013-09-05 21:49:37