2008-09-23 4 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]: ? 

Я собираю от Google поиск Я сделал, что эта функция была обесценились в 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); 

может быть то, что вам нужно.

Создает новый пустой стол и толкает на стек. В новой таблице есть пространство, предварительно выделенное для массива narr элементов и элементов nrec non-array. Это предварительное распределение полезно, когда вы точно знаете, сколько элементов будет иметь таблица . В противном случае вы можете использовать функцию lua_newtable.

+0

С другой стороны, .NET System.Collection.Hashtable имеет конструктор с параметром емкости. – Constantin 2008-09-24 00:21:03

1

Существует еще внутренний luaL_setn и вы можете скомпилировать Lua, так что она подвергается, как table.setn. Но похоже, что это не поможет , потому что код, похоже, не преподает.

(Также SETN, как отметили выше SETN относятся к части массива таблицы Lua, и вы сказали, что ваш используют таблицу ассоциативные массива)

Хорошая часть, что даже если вы добавите элементы один за другим, 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] = что-то. Это должно работать до предела оптимизированного размера массива, указанного в источниках Lua (2^26 = 67108864). После этого все ассоциативно.

p.s. Старый метод setn обрабатывал только часть массива, поэтому он не нужен для ассоциативного использования (игнорируйте эти ответы).

p.p.s. Изучали ли вы общие советы по поддержанию высокой производительности Lua? т. е. знать создание таблиц и скорее использовать таблицу, чем создавать новую, использовать «local print = print» и т. д., чтобы избежать глобальных доступов.

+0

Я не смотрел в исполнении Луа в целом, но я определенно заинтересован.На самом деле, я просто задал вопрос: http://stackoverflow.com/questions/154672/what-can-i-do-to-increase-the-performance-of-a-lua-program – 2008-09-30 19:52:11

1

Хотя это не отвечает на главный вопрос, он отвечает на ваш второй вопрос:

Кроме того, есть какой-то другой способ, чтобы избежать выделения памяти при добавлении объекта в таблице?

Если работает Lua в пользовательском приложении, как я догадываюсь, так как ваш делать кодирование C, я предлагаю вам заменить аллокатора с малым значением распределителем Локи, он уменьшил мои выделения памяти 100+ раза. Это улучшило производительность, избегая круглых поездок в ядро ​​и сделало меня намного более счастливым программистом :)

В любом случае я пробовал другие распределители, но они были более общими и предоставляли гарантии, которые не приносят пользы приложениям Lua (например, нить безопасность и распределение больших объектов и т. д.), а также создание собственного распределителя небольших объектов может быть хорошей неделей программирования и отладки, чтобы получить все в порядке, и после поиска доступного решения распределитель Loki был самым простым и быстрым, я нашел для этой проблемы.

2

Если объявить таблицу в коде с определенным количеством предметов, например, так:

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

затем Lua создать таблицу с памятью уже выделено, по крайней мере n пунктов.

Однако Lua использует технику выделения по 2 раза по возрастанию, поэтому добавление элемента в таблицу редко приводит к перераспределению.