Ich hab grad mal ein Beispiel gemacht, das veranschaulicht, wie die Dinge wirken. Ich teste mal 4 Ansatzweisen gegeneinander, es geht darum, eine Liste zu durchsuchen und eine Teilliste zu bilden. Die eigentliche Aufgabe ist ja, einen Strang in der Blocktabelle zu durchsuchen und alle Texte rauszupuhlen.
Ersatzweise mache ich folgendes: Ich nehme eine Liste aller Zahlen von 1 bis eine Million und durchsuche sie dann nach allen durch 2 teilbaren Zahlen *grins*. Die 4 Routinen machen das etwas unterschiedlich, und es wird die Zeit dafür gestoppt:
1. Ausser Konkurrenz läuft die Variante mit (append) - die ist so langsam, dass ich das Ergebnis wahrscheinlich erst in Wochen sagen könnte. Abgebrochen!
2. cons statt append, und zwei setq drin. Läuft in endlicher Zeit!
3. Wie 2, aber ein setq eliminiert.
4. Das zweite setq auch noch raus, keine Variablen mehr.
Festhalten, jetzt kommt der Code für das Profiling (Zeitermittlung). Näheres dazu gibt es auf meinen Advanced-Seiten, deshalb unkommentiert hier:
(defun safe-envelope(expr fences / )
(eval
(append
(list'lambda(cons '/ fences))
(list expr)
)
)
)
(defun elapsed(test-expr n-times / t1)
(setq t1(time-list))
(setq test-expr
(safe-envelope test-expr
'(test-expr n-times t1)
)
)
(repeat n-times
((eval test-expr))
)
(time-diff t1(time-list))
)
(defun time-list( / cd)
(setq cd(rtos(getvar"cdate")2 6))
(append
(list(atoi(substr cd 10 2)))
(list(atoi(substr cd 12 2)))
(list(atoi(substr cd 14 2)))
)
)
(defun time-diff(t1 t2 / r)
(setq r
(abs
(apply'-
(mapcar
'(lambda(tn / )
(+(* 3600(car tn))
(* 60(cadr tn))
(caddr tn)
)
)
(list t1 t2)
)
)
)
)
(list
(/ r 3600)
(/ (rem r 3600) 60)
(rem r 60)
)
)
Jetzt eine Hilfsfunktion, die die Testvariable mit 1000000 Zahlen erzeugt:
(defun mk-testvar( / i ) ; *testvar* ist global
(setq i 0)
(repeat 1000000
(setq *testvar*
(cons i *testvar*)
)
)
(length *testvar*)
)
Jetzt die 4 Vergleichsfunktionen:
(defun test1( / result)
(while *testvar*
(if(=(rem(car *testvar*)2)0)
(setq result
(append result(list(car *testvar*)))
)
)
(setq *testvar*(cdr *testvar*))
)
nil
)
(defun test2( / result)
(while *testvar*
(if(=(rem(car *testvar*)2)0)
(setq result
(cons(car *testvar*)result)
)
)
(setq *testvar*(cdr *testvar*))
)
nil
)
(defun test3( / result)
(foreach elm *testvar*
(if(=(rem(car *testvar*)2)0)
(setq result
(cons(car *testvar*)result)
)
)
)
nil
)
(defun test4( / )
(apply'append
(mapcar
'(lambda(n / )
(list(=(rem(car *testvar*)2)0))
)
*testvar*
)
)
nil
)
So, und nun zum Ergebnis. Wie gesagt, Variante 1 kann mal jemand laufen lassen, der den Rechner die nächsten Wochen nicht braucht;-)
(mk-testvar)
(princ(elapsed'(test2)1))
(terpri)
(mk-testvar)
(princ(elapsed'(test3)1))
(terpri)
(mk-testvar)
(princ(elapsed'(test4)1))
(princ)
=> (0 0 23) ; Nr. 2
=> (0 0 14) ; Nr. 3
=> (0 0 43) ; Nr. 4
Wie man sieht, muss man also vorsichtig abschätzen, wie man vorgeht. Das eine setq rauszunehmen, hat die Geschwindigkeit fast verdoppelt. Das zweite setq auch noch rauszunehmen, bringt hier aber nix, da wir dann zwei Durchläufe durch die Liste haben und doch wieder ein append drin haben, allerdings sehr entschärft, da nur 1 Aufruf in apply.
Und weil ich so gehässig bin, hier noch Variante 5 mit so einigen 'Stilblüten', wie man sie des öfteren sieht:
(defun test5( / result vergleich)
(foreach elm *testvar*
(if(=(rem(car *testvar*)2)0)
(setq vergleich 'T)
(setq vergleich nil)
)
(if(/= vergleich nil)
(setq result
(cons(car *testvar*)result)
)
)
)
nil
)
=> (0 0 56) ; kostet halt Rechenzeit!
Die Genauigkeit des Abstoppens hat übrigens ihre Grenzen, aber das Ganze kann ganz gut als Anhaltspunkt dienen.
So, jetzt aber Schluss mit den Romanen;-)
Gruss, Axel
------------------
http://www.tutorial.autolisp.info
http://www.advanced.autolisp.info
http://www.activex.autolisp.info
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP