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

Optimization 如何在Lua中预先调整数组的大小?,optimization,lua,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]: ? 我从谷歌搜索中得知,Lua5.1中的这个功能被贬低了,但我找不到什么(如果

我有一个Lua程序,看起来比它应该的慢。我怀疑问题在于我一次向关联数组添加一个值,而表每次都必须分配新内存

似乎确实存在table.setn函数,但在Lua 5.1.3下失败:

stdin:1: 'setn' is obsolete
stack traceback:
        [C]: in function 'setn'
        stdin:1: in main chunk
        [C]: ?
我从谷歌搜索中得知,Lua5.1中的这个功能被贬低了,但我找不到什么(如果有的话)替代了这个功能

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


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

我认为您不能这样做-它不是数组,而是关联数组,如perl哈希或awk数组

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

但是,如果在C端分配数组,则

void lua_createtable (lua_State *L, int narr, int nrec);
也许是你需要的

创建一个新的空表并推送 把它放在书堆上。这张新桌子有 为narr阵列预先分配的空间 元素和nrec非数组元素。 当您 确切地知道有多少元素 这张桌子有两张桌子。否则,您可以使用 函数lua_为新表


仍然有一个内部luaL_setn,您可以编译Lua以便 它以table.setn的形式公开。但看起来没用 因为代码似乎没有做任何预扩展

(此外,如上所述,setn与阵列部件相关 一个Lua表,您说您正在使用该表作为关联 阵列)

好的方面是,即使您逐个添加元素,Lua也不会 这样增加数组。相反,它采用了更合理的策略。你还是 为较大的阵列获得多个分配,但性能优于 每次都得到新的分配

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" );
然后,在卢阿

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

a = array(10)

作为运行此功能的快速方法,您可以将C添加到
lua.C

让我更关注您的问题:

向关联数组添加值 一次一个

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

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

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

p、 旧的“setn”方法只处理数组部分,因此它不用于关联用法(忽略这些答案)


p、 另外,您是否研究过保持Lua高性能的一般技巧?i、 e.了解表的创建,而不是重复使用表而不是创建新表,使用“local print=print”等避免全局访问。

虽然这并没有回答您的主要问题,但它回答了您的第二个问题:

或者,在向表中添加对象时,是否有其他方法可以避免内存分配

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


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

如果您用代码声明表,并带有特定数量的项,例如:

local tab = { 0, 1, 2, 3, 4, 5, ... , n }
然后Lua将创建一个表,其中至少有
n
项已经分配了内存


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

另一方面,.NET的System.Collection.Hashtable确实有一个带容量参数的构造函数。在内部,Lua表的整数键实际上存储在一个数组中。正如您所说,其余的存储在关联数组中。对于一般情况,这是一个合理的策略,但对于这个特定的程序,我确切地知道表需要有多大。我没有研究Lua的总体性能,但我肯定感兴趣。事实上,我只是问了一个问题:这个答案不是真的(再也不是了?),根据“Lua性能提示”(在这里获取),Lua分析表并将值放入哈希部分,如果数组部分小于array_N/2,那么构造
t={};t[100000]=true
将导致一个空数组部分和一个包含一个元素的散列部分。前几天我读这篇文章是为了好玩,但是如果你对lua性能感兴趣,你应该看看这篇关于lua实现的文章,它涉及了很多内部数据结构。是否有任何原因导致默认情况下不提供此选项?比如说,在表库中。