你如何预先在Lua中调整数组大小?

时间:2008-09-23 22:59:09

标签: optimization 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]: ?

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

你知道如何在Lua中预先调整表的大小吗?

或者,在向表中添加对象时,还有其他一些方法可以避免内存分配吗?

6 个答案:

答案 0 :(得分:9)

让我更专注于你的问题:

  

将值添加到关联数组   一次一个

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

所以..如果您确实要以关联方式添加值,请遵循上面的规则。

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

P.S。旧的'setn'方法仅处理数组部分,因此它不适用于关联用法(忽略这些答案)。

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

答案 1 :(得分:7)

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

答案 2 :(得分:5)

我认为你不能 - 它不是一个数组,它是一个关联数组,比如perl hash或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。

答案 3 :(得分:2)

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

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

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

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

答案 4 :(得分:1)

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

(另外上面注释的setn与setn相关,与数组部分有关 一个Lua表,你说你正在使用该表作为关联 阵列)

好的部分是,即使你逐个添加元素,Lua也不会 以这种方式增加阵列。相反,它使用更合理的策略。你还在 为更大的阵列获得多个分配,但性能优于 每次都获得新的分配。

答案 5 :(得分:1)

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

  

或者,在向表中添加对象时,还有其他一些方法可以避免内存分配吗?

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

无论如何我尝试了其他分配器,但是它们更通用,并且提供了不利于Lua应用程序的保证(例如线程安全,大对象分配等等),还编写了自己的小对象分配器可以是一个很好的编程和调试周,以便做到正确,并且在搜索可用的解决方案后,Loki的分配器是我发现的最简单和最快的问题。