如何在Lua中预设数组的大小?

我有一个 Lua 程序,似乎比应该的慢。我怀疑问题在于我一次只添加一个值到关联数组中,每次表都必须分配新的内存。

似乎有一个 table.setn 函数,但它在 Lua 5.1.3 下失败:

stdin:1: 'setn' is obsolete
stack traceback:
        [C]: in function 'setn'
        stdin:1: in main chunk
        [C]: ?

我从我做的 Google 搜索中得出,这个函数在 Lua 5.1 中被淘汰了,但我找不到代替此功能的东西(如果有的话)。

您知道如何在 Lua 中预设表的大小吗?

或者,添加对象到表中时是否有其他避免内存分配的方法?

原文链接 https://stackoverflow.com/questions/124455

点赞
stackoverflow用户18901
stackoverflow用户18901

我认为你不能这样做 - 它不是数组,它是一个关联数组,就像 Perl 哈希或 awk 数组。

http://www.lua.org/manual/5.1/manual.html#2.5.5

我认为你不能从 Lua 的角度有意义地预设它的大小。

不过,如果你正在 C 端分配数组,那么

void lua_createtable (lua_State *L, int narr, int nrec);

可能就是你需要的。

创建一个新的空表并把它压入堆栈中。新表已经为 narr 个数组元素和 nrec 个非数组元素预先分配了空间。当你知道表将有多少元素时,这种预分配是有用的。否则你可以使用函数 lua_newtable。

2008-09-23 23:28:45
stackoverflow用户15281
stackoverflow用户15281

还有一个内部的 luaL_setn 函数,你可以编译 Lua 来将其作为 table.setn 暴露出来。但看起来这并不能帮助你,因为代码似乎没有进行任何预分配。

(另外,上面注释中的 setn 是关于 Lua 表的数组部分的,而你说你正在将表用作关联数组)

好消息是,即使逐个添加元素,Lua 也不会以这种方式增加数组。相反,它使用了一个更合理的策略。你仍然会为一个更大的数组获得多个分配,但性能比每次获取新的分配要好。

2008-09-24 07:29:41
stackoverflow用户4121413
stackoverflow用户4121413
static int new_sized_table( lua_State *L )
{
    int asize = lua_tointeger( L, 1 );
    int hsize = lua_tointeger( L, 2 );
    lua_createtable( L, asize, hsize );
    return( 1 );
}

...

lua_pushcfunction( L, new_sized_table );
lua_setglobal( L, "sized_table" );

然后,在 Lua 中,

array = function(size) return sized_table(size,0) end

a = array(10)

作为一个快速的修复,您可以将 C 代码添加到 lua.c

2008-09-28 22:28:38
stackoverflow用户14455
stackoverflow用户14455

让我更专注于你的问题:

逐个将值添加到关联数组中

在 Lua 中,表是关联的,但以数组形式(1..N)使用它们是经过优化的。它们在内部有双重面。

所以.. 如果您确实在关联添加值,请遵循上述规则。

如果您使用索引 1..N,则可以通过设置 t [100000] = something 强制进行一次大小调整。这应该可以工作,直到 Lua 源代码中指定的优化数组大小的限制(2 ^ 26 = 67108864)。之后,一切都是关联的。

附言。旧的“setn”方法仅处理数组部分,因此对于关联使用无用(请忽略那些答案)。

附言。您是否学习过保持 Lua 性能高的一般提示?即了解表的创建,而是重用表而不是创建新表,使用“本地打印=打印”等来避免全局访问。

2008-09-30 12:49:26
stackoverflow用户15124
stackoverflow用户15124

虽然这并不能回答你的主要问题,但它可以解决你的第二个问题:

除此之外,是否有其他方式在将对象添加到表时避免内存分配?

如果你正在自定义应用程序中运行Lua,就像我猜测的那样,因为你在进行C编码,我建议你使用Loki的小值分配器来替换分配器,它将我的内存分配减少了100倍以上。这通过避免与内核往返大大提高了性能,使我成为更快乐的程序员 :)

无论如何,我尝试了其他分配器,但它们更加通用,并提供了对Lua应用程序没有益处的保证(如线程安全和大对象分配等...),而编写自己的小对象分配器可能需要一周时间来进行编程和调试,而在寻找可用解决方案后,Loki的分配器是我找到的最简单和最快的解决方案。

2008-11-28 01:48:58
stackoverflow用户1536
stackoverflow用户1536

如果您在代码中声明表并指定一定数量的项目,如下所示:

local tab = {0, 1, 2, 3, 4, 5, ..., n}

然后,Lua将为表创建预先分配至少 n 个项目的内存。

然而,Lua使用2倍的增量内存分配技术,因此向表中添加一个项目应该很少会强制进行重新分配。

2009-09-28 15:39:02