2008-09-23 23 views
7

Tengo un programa Lua que parece ser más lento de lo que debería ser. Sospecho que el problema es que estoy agregando valores a una matriz asociativa uno a la vez y la tabla tiene que asignar nueva memoria cada vez.¿Cómo se predimensiona una matriz en Lua?

Hay que parecen ser una función table.setn, pero falla en Lua 5.1.3:

stdin:1: 'setn' is obsolete 
stack traceback: 
     [C]: in function 'setn' 
     stdin:1: in main chunk 
     [C]: ? 

que deduzco de la búsqueda Google que he hecho que esta función se deprecia en Lua 5.1, pero no puedo encontrar qué (si acaso) reemplazó la funcionalidad.

¿Sabes cómo preajustar una mesa en Lua?

Alternativamente, ¿hay alguna otra forma de evitar la asignación de memoria cuando agrega un objeto a una tabla?

+0

Lo leí por diversión el otro día, pero si estás interesado en el rendimiento lua, deberías consultar este documento sobre la implementación de lua, revisa bastantes de las estructuras internas de datos. http://www.lua.org/doc/jucs05.pdf – Falaina

Respuesta

5

No creo que puedas, no es una matriz, es una matriz asociativa, como un hash Perl o una matriz awk.

http://www.lua.org/manual/5.1/manual.html#2.5.5

no creo que puede predeterminar su tamaño de manera significativa desde el lado Lua.

Si va a asignar la matriz en la parte C, sin embargo, el

void lua_createtable (lua_State *L, int narr, int nrec); 

puede ser lo que necesita.

Crea una nueva tabla vacía y la empuja a la pila . La nueva tabla tiene el espacio preasignado para los elementos narr array y nrec elementos que no son de matriz. Esta preasignación es útil cuando sabe exactamente cuántos elementos tendrá la tabla . De lo contrario, puede usar la función lua_newtable.

+0

Por otro lado, System.Collection.Hashtable de .NET tiene un constructor con parámetro de capacidad. – Constantin

1

todavía hay una luaL_setn interna y se puede compilar de manera que Lua que se expone como table.setn. Pero parece que no ayudará a porque el código no parece hacer ninguna extensión previa.

(También el SETN como se ha comentado anteriormente la SETN se relaciona con la parte variedad de una tabla Lua, y usted dijo que su están utilizando la tabla como asociativo matriz)

La parte buena es que incluso si agrega los elementos uno por uno, Lua no aumenta la matriz de esa manera. En cambio, usa una estrategia más razonable. Todavía tiene obtener asignaciones múltiples para una matriz más grande, pero el rendimiento es mejor que obteniendo una nueva asignación cada vez.

+0

Para situaciones genéricas, esa es una estrategia razonable, pero para este programa en particular sé exactamente qué tan grande debe ser la tabla. –

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"); 

Luego, en Lua,

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

a = array(10) 

Como un truco rápido para conseguir esto funcione se puede agregar el C a lua.c.

+0

¿Hay alguna razón por la cual esto no se proporciona por defecto? En, digamos, biblioteca de tablas. – Marko

9

Permítanme centrarme más en su pregunta:

agregar valores a una matriz asociativa uno a la vez

tablas en Lua son asociativos, pero su uso en una forma array (1 ..N) está optimizado. Tienen caras dobles, internamente.

Así que ... Si realmente está agregando valores asociativamente, siga las reglas anteriores.

Si está utilizando los índices 1..N, puede forzar un reajuste de tamaño único ajustando t [100000] = algo. Esto debería funcionar hasta el límite del tamaño optimizado de la matriz, especificado en las fuentes de Lua (2^26 = 67108864). Después de eso, todo es asociativo.

p.s. El antiguo método 'setn' solo manejaba la parte de la matriz, por lo que no sirve para el uso asociativo (ignore esas respuestas).

p.p.s. ¿Has estudiado consejos generales para mantener alto el rendimiento de Lua? es decir, conocer la creación de tablas y reutilizar una tabla en lugar de crear una nueva, el uso de 'print local' imprimir 'y así evitar los accesos globales.

+0

No he analizado el rendimiento de Lua en general, pero definitivamente estoy interesado.De hecho, acabo de hacer la pregunta: http://stackoverflow.com/questions/154672/what-can-i-do-to-increase-the-performance-of-a-lua-program –

+9

Esta respuesta no es verdad (¿más?), de acuerdo con los "consejos de rendimiento de Lua" (consíguelo aquí http://www.lua.org/gems/), Lua analiza la tabla y coloca valores en la parte hash si la parte de la matriz tiene menos de array_N/2, entonces el constructo 't = {}; t [100000] = true' daría como resultado una parte de matriz vacía y una parte de almohadilla con un elemento. – dualed

1

Aunque esto no responde a su pregunta principal, que responde a la segunda pregunta:

Alternativamente, ¿hay alguna otra manera de evitar la asignación de memoria cuando se agrega un objeto a una tabla?

si su funcionamiento Lua en una aplicación personalizada, como yo puede adivinar desde su hacer codificación C, sugiero que cambie el asignador con valor pequeño asignador de Loki, que redujo mis asignaciones de memoria de 100 se pliegan. Esta mejora en el rendimiento al evitar viajes ida y vuelta al núcleo, y me hizo un programador mucho más feliz :)

todas maneras, me trataron otros asignadores, pero eran más general, y proporcionar la garantía de que no se benefician aplicaciones LUA (como hilo seguridad, asignación de objetos grandes, etc.), también escribir su propio asignador de objetos pequeños puede ser una buena semana de programación y depuración para hacer las cosas bien, y después de buscar una solución disponible, el asignador de Loki fue el más fácil y rápido que encontré por este problema

2

Si se declara su mesa de código con una cantidad específica de artículos, así:

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

continuación LUA crear la tabla con la memoria ya asignado por lo menos n artículos.

Sin embargo, Lua usa la técnica de asignación de memoria incremental 2x, por lo que agregar un elemento a una tabla rara vez debe forzar una reasignación.