Hallo,
wenn ich aus zwei words ein dword machen will, kann ich ja schreiben
1
dwo=lowo+0x10000*hiwo
das modul 'bit32' bietet aber direkte Bit-Ops an (bei 5.2 schon fest
dabei)
1
dwo=bit32.bor(lowo,bit32.lshift(hiwo,16))
Wie ist das in Sachen Lesbarkeit und Rechengeschwindigkeit zu
vergleichen?
Mir persönlich gefällt die erste Variante besser.
Ok, beim Aufteilen müsste man schreiben
Jürgen W. schrieb:> Wie ist das in Sachen Lesbarkeit und Rechengeschwindigkeit zu> vergleichen?
Sieh zu, dass du einen Blick auf den erzeugten Code kriegst.
Für einen ordentlichen Compiler ist es ein leichtes, für beide Versionen
den gleichen Code zu erzeugen. Das Vereinfachen derartiger
Multiplikationen zu Bitoperationen bzw. zu einfacheren Versionen, die
dasselbe Ergebnis haben, machen übliche Compiler seit mehr als 40 Jahren
standardmässig. Ist ja auch kein wirkliches Problem.
> du einen Blick auf den erzeugten Code
Lua wird interpretiert.
D.h. ich müsste in den Lua-Interpreter schauen, wie er
Multiplitkationen/Divisionen mit 2er-Potenzen händelt.
Ich glaube nicht, dass er diese Zahlen erkennt und statt
Multiplikationen/Div. die shift-Operation aufruft. Denn der Interpreter
ist sehr klein (ca. 40 kB)
Jürgen W. schrieb:> Wie ist das in Sachen Lesbarkeit und Rechengeschwindigkeit zu> vergleichen?> Mir persönlich gefällt die erste Variante besser.
Dann ist ja schon gewählt, oder?
Oder hast du Performance Probleme? z.B. CHDK lässt ja Lua auf den Canon
Digicams laufen, die sind nicht besonders schnell...
Wenn du die Performance messen willst: Mach eine Schliefe, 10'000
durchläufe und miss die Zeit...
mfg Andreas
Karl Heinz Buchegger schrieb:> Das alleine ist noch kein Hindernisgrund.
Eher doch, und Deine obige Bemerkung
>Sieh zu, dass du einen Blick auf den erzeugten Code kriegst.
hat mich schon etwas erschreckt.
Lua wird, wie auch andere Scriptsprachen wie Python und Ruby, kein
Assemblerlisting erzeugen können, dass man sich ansehen kann. Auch wenn
intern Bytecode erzeugt wird -- erstens wird man den nicht zu Gesicht
bekommen, und zweitens würde man damit wohl nicht viel anfangen können,
soferm man keine entsprechende Virtuelle Maschiene ist.
Und da die erwähnten Sprachen eher jung sind, kann sich bezüglich
Performance mit jeder neuen Version viel ändern. So macht es eher wenig
Sinn, überhaupt nach Performance zu fragen, solange man nicht ein
Problem damit hat. Bleibt also das Kriterium der Lesbarkeit.
>Dann ist ja schon gewählt, oder?
Nicht ganz. In einigen Fällen zB bit setzen oder löschen ist bit32 schon
angenehmer. Die Frage ist eher ob man überhaupt noch diese
bit-Konstrukte nimmt. Ich bin halt von C geprägt.
Auch ist zu bedenken, dass man zu Lua 5.1 kompatibel sein möchte.
>Und da die erwähnten Sprachen eher jung
Trifft bei Lua nicht zu
Salewski, Stefan schrieb:> Eher doch, und Deine obige Bemerkung>>>Sieh zu, dass du einen Blick auf den erzeugten Code kriegst.>> hat mich schon etwas erschreckt.
Da wusste ich noch nicht, dass Lua 'interpretiert' wird.
Aber wie alle ernst zu nehmende Interpreter-Ansätze, wird der
Programmtext ja zumindest in einen Zwischencode übersetzt. Und genau da
ist dann der Punkt an dem man derartige Optimierungen unterbringt.
Ob der Lua Compiler das macht oder nicht, weiß ich nicht.
> Bleibt also das Kriterium der Lesbarkeit.
Ganz genau.
Jürgen W. schrieb:>>Und da die erwähnten Sprachen eher jung> Trifft bei Lua nicht zu
Nun ja, was ist jung?
Ruby ist gerade 20 geworden, Python ist etwas älter -- Teenager halt,
noch keine ausgereiften Persönlichkeiten. Lua würde ich auch so um die
20 schätzen. Ruby ist "jung", weil es eine sehr komplexe Sprache ist und
die Entwicklung langsam voranschreitet. Von Version 1.8.x nach 1.9/2.0
hat sich viel getan, insbesondere ist durch den Bytecode-Interpreter die
Performance stark gestiegen und hat nahezu zu Python aufgeschlossen.
Wichtig ist ja noch, dass es meist verschiedene Interpreter gibt --
etwa JRuby oder das experimentelle Topaz, und für Python etwa PyPy, was
wohl schon eher ein Compiler ist. Daher macht die allgemeine Frage nach
Performance wenig Sinn.
Und nun habe ich doch nachgesehen -- Lua ist auch gerade 20 geworden
http://de.wikipedia.org/wiki/Lua
Mit jung hätte ich Sprachen wie angelscript eingestuft. 20 Jahren sind
ja schon eine Menge.
Als ich mit C Mitte der 80er anfing, war diese gerade 15 Jahren alt, und
mir erschien das nicht "jung".
Von Lua habe erst vor ein paar Jahren gehört, als ein Ex-Kollege davon
schwärmte (Spiele-Programmierer)
Die Bit-Operationen sind nicht das einzige Problem, andere Sachen
(Array-Indizierweise) machen mir auch zu schaffen. Aber die Einfachheit,
Erweiterbarkeit und Stabilität der Sprache überzeugt.
Bei Interpretern (auch Bytecode-Interpretern) spielt die Zeit für die
Ausführung primitiver Rechenoperationen kaum eine Rolle, zumal auf einem
PC Addition, Multiplikation, Bit-Or und Bit-Shift sowieso ungefähr
gleich lang dauern.
Wesentlich mehr Zeit brauchen i.Allg. die Dekodierung der Befehle, das
Auffinden von Variablen und die Verwaltung des internen Interpreter-
zustands.
Hier sind die Disassemblies des vom Compiler generierten Bytecodes für
die beiden Anweisungen (du erhältst sie mit luac -l test.lua):
1
dwo = lowo + 0x10000 * hiwo
2
10 [7] GETTABUP 4 0 -5 ; _ENV "lowo"
3
11 [7] GETTABUP 5 0 -3 ; _ENV "hiwo"
4
12 [7] MUL 5 -10 5 ; 65536 -
5
13 [7] ADD 4 4 5
6
14 [7] SETTABUP 0 -9 4 ; _ENV "dwo"
1
dwo = bit32.bor(lowo, bit32.lshift(hiwo,16))
2
10 [8] GETTABUP 4 0 -2 ; _ENV "bit32"
3
11 [8] GETTABLE 4 4 -10 ; "bor"
4
12 [8] GETTABUP 5 0 -5 ; _ENV "lowo"
5
13 [8] GETTABUP 6 0 -2 ; _ENV "bit32"
6
14 [8] GETTABLE 6 6 -11 ; "lshift"
7
15 [8] GETTABUP 7 0 -3 ; _ENV "hiwo"
8
16 [8] LOADK 8 -12 ; 16
9
17 [8] CALL 6 3 0
10
18 [8] CALL 4 0 2
11
19 [8] SETTABUP 0 -9 4 ; _ENV "dwo"
Der Code sollte dank der vom Compiler eingefügten Kommentare weitgehend
selbsterklärend sein.
Die erste Variante braucht auf meinem Pentium 4 mit 3,2 GHz 143 ns. Die
zweite Variante ist länger, macht mehr zeitaufwendige Symbol-Lookups und
braucht deswegen mit 533 ns deutlich länger.
Zwei Lookups kann man in der zweiten Variante einsparen, indem man
bit32.bor und bit32.shift am Programmanfang Variablen zuweist, so dass
bei der eigentlichen Rechenoperation bit32 nicht mehr nachgeschlagen
werden muss. Dann dauert diese Variante nur noch 462 ns, ist aber immer
noch deutlich langsamer als die erste Variante.
Yalu X. schrieb:> Hier sind die Disassemblies des vom Compiler generierten Bytecodes für> die beiden Anweisungen
Puh -- da habe ich echt mal was gelernt hier im Forum.
Das hätte ich nun echt nicht erwartet, dass man fur Lua den
kommentierten Bytecode ansehen kann.
Ich denke mal für Ruby geht das nicht, jedenfalls habe ich da noch nie
von gehört -- ich werde aber demnächst mal danach suchen, auch für
Python.
Aber meine anderen Argumente entkräftet das nicht wirklich -- mit jeder
neuen Interpreterversion oder mit einem anderen Interpreter/Compiler
kann das ganz anders aussehen, und wenn man Sprachen wie Lua/Python/Ruby
nutzt steht die Ausführungsgeschwindigkeit meist nicht im Vordergrund.
Die Lesbarkeit/Verstehbarkeit ist dann wichtiger.
Salewski, Stefan schrieb:> Lua wird, wie auch andere Scriptsprachen wie Python und Ruby, kein> Assemblerlisting erzeugen können, dass man sich ansehen kann.
Zumindest Python kann das. Lua ja anscheinend auch.
Auch die Compiler-Entwickler brauchen ja irgendwelche Tools, mit denen
der vom Compiler erzeugte Bytecode in lesbarer Form angezeigt werden
kann. Deswegen muss entweder der Compiler selbst die Möglichkeit bieten,
Assembler-Quellcode zu erzeugen, oder es gibt einen Disassembler, oder
beides. Da diese Tools sowieso schon existieren, sind sie in Opensource-
und oft auch in Closedsource-Toolchains auch für den Compiler-Anwender
verfügbar.