2008-09-23 420 views
7

我有一个似乎比它应该慢的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中预先设定一个表吗?

另外,有没有其他的方式来避免内存分配时,你添加一个对象到表?

+0

我前些日子读了这篇文章,但如果你对lua的性能感兴趣,你应该看看这篇关于lua实现的文章,它覆盖了很多内部数据结构。 http://www.lua.org/doc/jucs05.pdf – Falaina 2009-09-28 15:41:32

回答

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非数组元素。 当您准确知道 表具有多少个元素时,此预分配很有用。否则,您可以使用 函数lua_newtable。

+0

另一方面,.NET的System.Collection.Hashtable确实有一个带有容量参数的构造函数。 – Constantin 2008-09-24 00:21:03

1

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

(亦作评论的SETN以上是有关一个Lua表的阵列部分 ,你说你正在使用的表作为关联 数组SETN)

好部分是,即使如果你逐个添加元素,Lua不会以这种方式增加数组。相反,它使用更合理的策略。你仍然在 获得一个更大阵列的多个分配,但是性能比 每次都获得一个新的分配要好。

+0

对于一般情况,这是一个合理的策略,但对于这个特定的程序,我确切知道表格需要多大。 – 2008-09-24 17:15:49

5
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

+0

有没有任何理由为什么这不是默认提供的?在,可以说,表库。 – Marko 2016-07-12 10:58:59

9

让我更专注于你的问题:

同时

表在Lua是关联的增加值的关联数组 之一,但在一个阵列的形式使用它们(1 ..N)进行了优化。他们在内部有双重面孔。

所以..如果你真的是联想地增加价值,按照上面的规则。

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

p.s.旧的'setn'方法只处理数组部分,所以对于关联使用(忽略这些答案)是没有用的。

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

+0

我一直没有看过Lua的表现,但我绝对有兴趣。实际上,我只是问了这个问题:http://stackoverflow.com/questions/154672/what-c​​an-i-do-to-increase-the-performance-of-a-lua-program – 2008-09-30 19:52:11

1

虽然这并不回答您的主要问题,它回答你的第二个问题:

另外,有一些其他的方式,以避免内存分配,当你添加一个对象到表?

如果你运行的Lua在自定义应用程序,我可以猜到,因为你做的C语言的表达,我建议你更换Loki的小值分配器分配器,它减少了我的内存分配超过100倍。这通过避免往返内核的性能,并使我更快乐的程序员:)

反正我试过其他分配器,但他们更一般,并提供保证,不利于Lua应用程序(如线程安全性和大对象分配等等),编写自己的小对象分配器可以是编程和调试的一个良好的一周,以便恰到好处,并且在搜索可用的解决方案之后,Loki的分配器浪费了最简单和最快的方式对于这个问题。

2

如果你宣布你的表中的代码与项目的具体金额,就像这样:

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

那么的Lua将创建已分配至少n项目存储器中的图表。

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

相关问题