如何在不每次都查找的情况下从C++中执行Lua函数?

我是Lua的新手,正在研究如何从C++程序中嵌入/使用它。我已经具备了基本机制,但有兴趣让代码尽可能快地执行。因此,我正在加载/编译可以稍后使用的包含多个函数的lua代码。

现在假设我有一个名为'add'的lua函数,我想从C++中调用它。据我所知,我必须使用lua_getglobal()函数,它似乎可以找到并将'add'的字节码推到Lua堆栈上。我能否消除查找部分,即我能否保留到函数'add'的字节码的引用,以便我在需要时可以简单地将其推到堆栈上?当有成千上万个lua函数时,我不知道lua_getglobal()的效率如何,也不喜欢过早优化,但我正在尝试构建一个硬实时系统(是的,实际的物理截止日期,不仅仅是快速),如果我必须赶在短时间内调用'add'数十万次,每次都必须查找函数似乎是一种浪费。

此外,出于好奇,实际的字节码是否被推到堆栈上(即复制),还是只是引用它?我希望是后者。

提前致谢

点赞
用户734069
用户734069

lua_getglobal 的本质是进行表查找,与执行 lua_getfield 函数没有本质区别。Lua 表是哈希表,因此无论条目数量如何,查找效率都是摊销常数时间。

这并不意味着这样的获取非常快速。但是,查找的性能与表中不同项的数量无关。

至于能否将函数存储在某个地方以实现更快速的访问……不行,或者说不合理。

Lua 值无法存储在 C 代码中。虽然您可以从 Lua 值中获取数字或字符串,但无法以任何有意义的方式获取 Lua 函数。您可以调用 lua_topointer,但无法撤消该转换。

不过,您可以创建一个从主要 lua_State 派生出来的子 lua_State,并在其中加载其堆栈中的函数。使用堆栈索引比进行哈希表查找更快。当调用此函数时,您将使用 lua_xmove 将函数从子 lua_State 移动到主状态中以便执行。

当然,这样做会使您的代码更难阅读。一个简单的 lua_getglobal(L, "add")lua_pushvalue(Funcs, some_int)/lua_xmove(L, Funcs) 更有意义。使用全局表也允许您更改该值,从而导致所有对其的访问产生新函数。

此外,尚不清楚可以允许 lua_State 的堆栈有多大。因此,您可能没有足够的空间来使其正常工作。

最后,访问函数并不会复制实际内存。但是将垃圾回收对象放在堆栈上意味着其 GC 数据必须更新,以说明它被堆栈引用。因此,这不仅仅是指针复制。

2016-06-05 04:09:28
用户3586583
用户3586583

我能否省略查找部分,即我能否保留函数“add”的字节码引用,以便在需要使用它时将其直接推入堆栈?

你可以尝试使用luaL_Ref来创建对函数的引用。这个引用应该比较快速 - 似乎它使用了一个索引为数字的表,所以它可能比使用字符串键的哈希表更快。

在C中,尽可能使用lua_ref()。从速度上讲,lua_ref()的行为类似于一个本地变量。 - Lua,v4.0之前

我试着做了一些测试,用1000000000次将tonumber推入堆栈,结果发现lua_getglobal耗时24秒,有引用的rawgeti只用了12秒,两个堆栈和lua_pushvalue + lua_xmove用了11秒,而使用相同状态的lua_pushvalue和实际函数位于堆栈顶部用了6秒。

请查看此代码:http://pastebin.com/n8Q0uVx1

http://www.lua.org/manual/5.3/manual.html#luaL_ref http://www.lua.org/manual/5.3/manual.html#luaL_unref

2016-06-05 10:38:27