2008-09-23 417 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增量內存分配技術,因此向表中添加項目時很少會強制重新分配。

相關問題