9

我有一个 Lua 程序,它似乎比它应该的要慢。我怀疑问题是我一次向关联数组添加一个值,并且表每次都必须分配新内存。

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

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

我从谷歌搜索中收集到这个功能在 Lua 5.1 中被贬值了,但我找不到什么(如果有的话)取代了这个功能。

你知道如何在 Lua 中预先设置表格的大小吗?

或者,当您将对象添加到表时,是否有其他方法可以避免内存分配?

4

6 回答 6

11

让我更专注于你的问题:

一次将值添加到关联数组

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

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

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

ps 旧的 'setn' 方法只处理数组部分,所以它对关联使用没有用(忽略那些答案)。

pps 你研究过保持 Lua 高性能的一般技巧吗?即知道表的创建,宁愿重用一个表而不是创建一个新的,使用'local print=print'等来避免全局访问。

于 2008-09-30T12:49:26.150 回答
8
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-28T22:28:38.490 回答
5

我不认为你可以 - 它不是一个数组,它是一个关联数组,就像一个 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);

可能是你需要的。

创建一个新的空表并将其推入堆栈。新表已为 nrec 数组元素和 nrec 非数组元素预先分配了空间。当您确切知道表将包含多少元素时,此预分配很有用。否则你可以使用函数 lua_newtable。

于 2008-09-23T23:28:45.603 回答
1

虽然这不能回答您的主要问题,但它回答了您的第二个问题:

或者,当您将对象添加到表时,是否有其他方法可以避免内存分配?

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

无论如何,我尝试了其他分配器,但它们更通用,并提供不利于 Lua 应用程序的保证(例如线程安全和大对象分配等),也可以编写自己的小对象分配器良好的一周编程和调试得到了恰到好处,在寻找可用的解决方案之后,Loki 的分配器是我为这个问题找到的最简单和最快的。

于 2008-11-28T01:48:58.677 回答
1

仍然有一个内部的 luaL_setn,你可以编译 Lua 使其暴露为 table.setn。但看起来它无济于事,因为代码似乎没有做任何预扩展。

(此外,setn 上面评论的 setn 与 Lua 表的数组部分有关,您说您正在使用该表作为关联数组)

好的部分是,即使你一个一个地添加元素,Lua 也不会那样增加数组。相反,它使用了更合理的策略。您仍然可以为更大的数组获得多个分配,但性能比每次都获得新的分配要好。

于 2008-09-24T07:29:41.143 回答
1

如果您在代码中使用特定数量的项目声明您的表,如下所示:

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

然后 Lua 将创建至少已为n项目分配内存的表。

但是,Lua 使用 2x 增量内存分配技术,因此向表中添加项目很少会强制重新分配。

于 2009-09-28T15:39:02.003 回答