LuaJIT:一个脚本访问全局变量的次数是多少?

3

我正在尝试优化我的LuaJIT代码,我想知道是否有调试工具,或者我能否编写一个来检查我的脚本访问全局变量/表/函数的次数?


只需在_G上放置一个元表,该元表注册__index__newindex函数。这也在“Lua编程”中进行了解释。 https://www.lua.org/pil/14.2.html - Henri Menke
2个回答

1
你可以使用代理表来存储全局变量,并将对全局表的任何访问重定向到带有跟踪功能的代理表。
local globals = {}
setmetatable(_G, {
    __newindex = function (_, k, v)
        print(debug.traceback("Setting global variable " .. k, 2))
        rawset(globals, k, v)
    end,
    __index = function (_, k)
        print(debug.traceback("Getting global variable " .. k, 2))
        return rawget(globals, k)
    end,
})

a = 1
a = 2

print(a)

样例输出:

Setting global variable a
stack traceback:
    prog.lua:15: in main chunk
    [C]: at 0x00404960
Setting global variable a
stack traceback:
    prog.lua:16: in main chunk
    [C]: at 0x00404960
Getting global variable a
stack traceback:
    prog.lua:18: in main chunk
    [C]: at 0x00404960
2

在Wandbox上的实时示例


谢谢,非常好用!还有wandbox的链接也谢谢。我甚至不知道有这么多语言可以在一个网站上运行代码。已点赞和接受,但没有声望。 - user10894418
@MorsMortium - 将 local globals = {} 替换为 local globals=_G; _G={}; setfenv(1, _G); setfenv(0, _G) - Egor Skriptunoff
这给了我一个错误:尝试调用全局变量'setfenv'(一个空值)。 - user10894418
@globals.setfenv - Henri Menke
这样做是可以的,但如果我写globals.setfenv(1, _G),那么它会将_G设置为nil,因此globals.setfenv(0, _G)会抛出一个错误,表示它是空的。如果我省略(1, _G)版本,那么setmetatable中的print函数将导致堆栈溢出,我不得不用io.write替换它,但现在它可以工作了!谢谢你们! - user10894418
显示剩余4条评论

0

如果有人在想,这是我写的最终代码,结合了注释和原始答案。它可以输出用户定义和内置全局变量的访问情况。 gnumber 和 snumber 只是计数器,可以打印出全局变量被设置或检索的总次数。

local globals = _G
_G = {}
local gnumber, snumber = 0, 0
globals.setfenv(0, _G)

setmetatable(_G, {
    __newindex = function (_, k, v)
        snumber = snumber + 1
        io.write("Setting global variable ", k, "\n")
        io.write(debug.traceback(), "\n")
        rawset(globals, k, v)
    end,
    __index = function (_, k)
        gnumber = gnumber + 1
        io.write("Getting global variable ", k, "\n")
        io.write(debug.traceback(), "\n")
        return rawget(globals, k)
    end,
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接