我有一个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中预先调整表的大小吗?
或者,在向表中添加对象时,还有其他一些方法可以避免内存分配吗?
答案 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的分配器是我发现的最简单和最快的问题。