Lua - 重新设置脚本的状态而不重新分析它

时间:2016-02-16 14:31:08

标签: c performance lua reset

我有一个运行Lua脚本的应用程序。每个Lua脚本可能会运行几次。每次按下某个键时,某些脚本甚至可能会运行。

我希望这些脚本在每次运行之间“重置”。即如果用户设置变量Foo,则下次运行时脚本中不应存在Foo,直到用户再次定义它为止。

问题是,如果我想要这样的行为,我需要每次都创建一个新的lua_State,然后每次都打开它,然后每次解析脚本文件,这看起来非常不优化。

加载库可能是一个相当轻量级的操作(我假设),但解析脚本可能不是。

有没有办法重置Lua脚本的状态(即清除用户代码定义的变量)而不创建新的lua_State并重新整理整个Lua脚本文件?我希望在应用程序启动时解析一次脚本文件,因为它们在运行时不会被修改。

谢谢。 :)

编辑:我找到了这个主题,但没有详细说明:http://lua-users.org/lists/lua-l/2006-01/msg00493.html

编辑:lua_setfenv似乎与此有关。我会再多挖一点。

编辑:从LUA 5.2开始,似乎没有更多的lua_setfenv。由于我使用的是5.3,我必须设置环境(即隐藏的表nammed _ENV,其中存储了变量)才能这样做,从而重新加载所有内容,这就是我不想做的事情......

3 个答案:

答案 0 :(得分:1)

不幸的是,上次我调查这个时答案是否定的。

您还需要记住,Lua可能会调用库,可能会打开文件,malloc()内存等,并且任何“重置”文件都可以。需要处理关闭这些文件,释放内存等等。

作为重置'的替代方案。在Lua状态下,您可以简单地组织代码,这样就不需要重置;这显然需要以特定的方式编写Lua代码。一种方法是坚持你的Lua代码完全(或几乎完全)包含在函数中,并为每个动作调用一个或多个函数。函数外部的代码可能(例如)返回一个Lua表,该表包含对特定入口点的调用的引用;这只会被调用一次。调用时,函数将自行清除,包括清除任何库分配项,打开文件等。应避免使用全局变量(除非常量)。我们成功地使用这种方法来确保Lua只被解析一次,入口点确定一次,但相对较小的函数可以非常快速地调用而且开销很小。

在您建议的注释中,您可以将Lua代码词法包装在功能块中。我认为这不如上述方法灵活,并具有以下缺点:

  • 你失去了做一次初始化的机会。 (例如,从磁盘读取固定常量)

  • 如果用户在代码中插入(例如)不匹配的end ... function B()

  • ,您将面临无法预料的风险
  • 您将自己限制在每个Lua州的一个入口点。

这确实意味着Lua代码必须以不同的方式编写(实质上Lua编码器以所需的形式提供代码)。解决此问题的一种可能方法是使用固定框架执行此操作,并在代码中require作为库调用。我没有尝试过那种方法。

答案 1 :(得分:1)

如果要确保每次脚本调用时lua_State都相同,还可以尝试以下适用于我的情况的方法:

  • 将自定义内存分配器传递给lua_newstate,后者从内存池分配内存
  • 在解析脚本之后并且在第一个“运行”之前,在其他一些内存位置创建内存池的备份
  • 每次“运行”后,从备份中将存储池还原到原始位置

请注意,这仅处理完全包含在Lua数据结构中的资源,而不处理通过Lua或Lua库以任何方式引用的“外部”资源(例如,文件描述符,userdata等)

因此,在我的情况下,我还通过替换globals表将脚本编写器的功能限制在某些沙箱中,仅提供对上述用法安全的操作。

使用这种方法,在每次“运行”之后,重置基本上可以归结为一些scaleLinear(-1)调用,因此,复制脚本的Lua结构所使用的内存所需的时间长。

答案 2 :(得分:0)

你不能清除lua_State吗?删除所有线程和手动设置的全局变量。您可能需要将用户环境与全局环境分开。