2008-09-23 8 views
7

Ich habe ein Lua-Programm, das langsamer zu sein scheint, als es sein sollte. Ich vermute, dass das Problem ist, dass ich Werte zu einem assoziativen Array einzeln hinzufüge und die Tabelle jedes Mal neuen Speicher zuweisen muss.Wie skaliert man ein Array in Lua?

Es schien eine table.setn Funktion zu sein, aber es funktioniert nicht unter Lua 5.1.3:

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

entnehme ich die Google getan, was ich habe die Suche, dass diese Funktion in Lua 5.1 abgeschrieben wurde, aber ich kann nicht finden, was (wenn überhaupt) die Funktionalität ersetzt hat.

Wissen Sie, wie man einen Tisch in Lua vorfasst?

Gibt es alternativ eine andere Möglichkeit, Speicherzuweisung zu vermeiden, wenn Sie ein Objekt zu einer Tabelle hinzufügen?

+0

Ich lese das aus Spaß vor ein paar Tagen, aber wenn Sie in Lua Leistung interessiert sind, sollten Sie dieses Papier über die Implementierung von Lua, es geht über einige der internen Datenstrukturen. http://www.lua.org/doc/jucs05.pdf – Falaina

Antwort

5

Ich glaube nicht, dass Sie können - es ist kein Array, es ist ein assoziatives Array, wie ein Perl-Hash oder ein awk-Array.

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

Ich glaube nicht, dass Sie seine Größe nach Bedeutung der Lua Seite voreinstellen.

Wenn Sie das Array auf der C-Seite sind die Zuteilung, die

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

kann aber sein, was Sie brauchen.

Erstellt eine neue leere Tabelle und schiebt es auf den Stapel. Die neue Tabelle hat Speicherplatz reserviert für Narr Array Elemente und NREC Nicht-Array-Elemente. Diese Vorbelegung ist nützlich, wenn Sie genau wissen, wie viele Elemente die Tabelle haben wird. Ansonsten können Sie die Funktion lua_newtable verwenden.

+0

Auf der anderen Seite, .NET System.Collection.Hashtable hat einen Konstruktor mit Kapazitätsparameter. – Constantin

1

Es gibt immer noch eine interne luaL_setn und Sie können Lua kompilieren, so dass es als table.setn ausgesetzt ist. Aber es sieht so aus, als würde es nicht helfen, , weil der Code keine Vorverlängerung zu tun scheint.

(auch als SETn über dem SETn kommentiert eines Lua-Tabelle mit dem Array-Teil verbunden ist, und Sie sagten, dass Ihr die Tabelle als assoziatives Array verwenden)

Das gute Teil ist, dass selbst Wenn Sie die Elemente nacheinander hinzufügen, erhöht Lua das Array nicht um . Stattdessen verwendet es eine vernünftigere Strategie. Sie immer noch erhalten mehrere Zuordnungen für ein größeres Array, aber die Leistung ist besser als bekommen jedes Mal eine neue Zuordnung.

+0

Für generische Situationen ist das eine vernünftige Strategie, aber für dieses spezielle Programm weiß ich genau, wie groß die Tabelle sein muss. –

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

Dann in Lua,

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

a = array(10) 

als schneller Hack diese zum Laufen bringen Sie die C lua.c hinzufügen können.

+0

Gibt es einen Grund, warum dies nicht standardmäßig vorgesehen ist? Zum Beispiel in der Tabellenbibliothek. – Marko

9

Lassen Sie mich mehr auf Ihrer Frage konzentrieren:

Hinzufügen von Werten zu einem assoziativen Array einen nach dem anderen

Tabellen in Lua assoziativ sind, sondern sie in einem Array-Formular (1 ..N) ist optimiert. Sie haben innen zwei Gesichter.

Also .. Wenn Sie in der Tat Werte hinzufügen, assoziativ, befolgen Sie die oben genannten Regeln.

Wenn Sie Indizes 1..N verwenden, können Sie eine einmalige Größenänderung erzwingen, indem Sie t [100000] = etwas setzen. Dies sollte bis zum Limit der optimierten Array-Größe funktionieren, die in Lua-Quellen angegeben ist (2^26 = 67108864). Danach ist alles assoziativ.

p.s. Die alte 'setn'-Methode behandelte nur den Array-Teil, daher ist sie für assoziative Verwendung nicht geeignet (ignoriere diese Antworten).

S.p.s. Haben Sie allgemeine Tipps zur Aufrechterhaltung der Lua-Leistung studiert? d. h. Tabellenerstellung kennen und eher eine Tabelle wiederverwenden als eine neue erstellen, Verwendung von 'local print = print' und so, um globale Zugriffe zu vermeiden.

+0

Ich habe Lua Leistung im Allgemeinen nicht untersucht, aber ich bin definitiv interessiert.In der Tat habe ich nur die Frage gestellt: http://stackoverflow.com/questions/154672/what-can-i-do-to-crease-the-performance-of-a-lua-program –

+9

Diese Antwort ist nicht wahr (mehr?), laut "Lua Performance Tips" (erhalten Sie es hier http://www.lua.org/gems/), Lua analysiert die Tabelle und setzt Werte in den Hash-Teil, wenn der Array-Teil weniger als array_N/2, also das Konstrukt 't = {}; t [100000] = true dualed

1

Obwohl dies nicht Ihre wichtigste Frage beantworten, es beantwortet Ihre zweite Frage:

Alternativ

, gibt es eine andere Art und Weise der Speicherzuordnung zu vermeiden, wenn Sie ein Objekt in eine Tabelle hinzufügen?

Wenn Sie Ihr Lauf Lua in einer benutzerdefinierten Anwendung, wie ich denke, kann, da Ihre C-Codierung zu tun, empfehle ich Ihnen das allocator mit Lokis kleinem Wert allocator ersetzen, es reduzierte meine Speicherzuordnungen falten 100+. Dies verbesserte die Leistung durch Vermeidung von Rundreisen zum Kernel, und machte mich zu einem viel glücklicheren Programmierer :)

Anyways ich versuchte andere Zuweiser, aber sie waren allgemeiner, und bieten Garantien, die nicht Lua-Anwendungen (wie Thread Sicherheit, und große Objektzuordnung, etc ...), auch das Schreiben Ihres eigenen kleinen Objektzuordners kann eine gute Woche des Programmierens und des Debuggens sein, um genau zu kommen, und nach der Suche nach einer verfügbaren Lösung Lokis Zuordner war das einfachste und schnellste, das ich fand für dieses Problem.

2

Wenn Sie Ihren Tisch in Code mit einer bestimmten Menge von Elementen zu erklären, etwa so:

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

dann Lua wird die Tabelle mit Speicher erstellen bereits für mindestens n Artikel zugeordnet.

Allerdings verwendet Lua die 2x inkrementelle Speicherzuweisungstechnik, sodass das Hinzufügen eines Elements zu einer Tabelle selten eine Neuzuweisung erzwingen sollte.