If-Statement beschleunigen 2 a
Die Optimierung im vorgehenden Beispiel war so einfach, dass man Optimierung ohne weiteres durchführen kann. Wenn die Struktur der Bedingung jedoch komplizierter gestaltet ist, muss man Vorkehrungen treffen um sicherzustellen, dass die Logik des Statements nicht geändert. Das kann zu Fehlern führen, die sich erst später bzw. an anderer Stelle im Quellcode bemerkbar machen. Für diesen Fehler die Ursache zu finden ist mühsam und zeitaufwendig! Darüber hinaus möchte man natürlich auch wissen, ob die Anstrengungen der Optimierung überhaupt Früchte trägt. Also brauchen wir einen Mechanismus zum Messen der Ausführungszeit.
Zeitmessung
Die grundlegende Funktion zur Zeitmessung ist die Funktion getTimer(). Sie liefert die vergangen Millisekunden seit dem 1. Jannuar 1970(Weiß eigentlich jemand warum genau dieses Datum? Mein Informatikprofessor konnte mir diese Frage damals nicht beantworten). Der Quellcode zu einer Messung könnte folgender Maßen aussehen:
- var _start:int = getTimer();
- // ...
- // zu messender code
- // ...
- var _finish:int = getTimer();
- trace("ausführungsdauer:",(_finish-_start));
Funktionsprüfung
Hier wieder ein If-Statement aus meinem aktuellen Projekt(Ist die nicht wunderschön= ;-) Na, wenn da kein Potential zur Optimierung drin steckt. Ich weiß es selbst noch nicht.):
- function test():Boolean{
- if(
- (! (diodeMidLeft & 1) && ( !climbing || !ladderMidRight && climbing ) )
- ||
- (! (diodeTopLeft & 1) && ( !climbing || !ladderTopLeft && climbing ) )
- )
- return true;
- else
- return false;
- }
Um sicher zu stellen, dass wir die Funktion nicht verändern, müssen wir zunächst einmal analysieren, was da alles abgefragt wird. Anschließend müssen wir uns eine Tabelle erstellen, in der wir für jede mögliche Kombination der einzelnen Bedingungen das Funktionsergebnis speichern. Und nach der Optimierung müssen wir prüfen, ob die Ergebnisse der neuen Funktion mit den Ergebnissen alten ident sind. Analyse: diode ist eine klasse mit statischen Konstanten. climbing ist ein boolean Wert. _tiles ist ein Array mit Objekten, wobei uns hier nur die Members diode(int) und ladder(Boolean) interessieren _level ist ein zweidimensionales Array, mit Zahlen, die auf _tiles verweisen.
Zunächst werden wir die Struktur etwas vereinfachen:
- Konstanten werden mit deren Wert ersetzt.
- Die Arrays werden durch einfache Variablen ersetzt.
- function test():Boolean{
- if(
- (! (diodeMidLeft & 1) && ( !climbing || !ladderMidRight && climbing ) )
- ||
- (! (diodeTopLeft & 1) && ( !climbing || !ladderTopLeft && climbing ) )
- )
- return true;
- else
- return false;
- }
Nun müssen wir festlegen welche Werte zum Prüfen verwenden müssen, um alle Fälle abzudecken.
Ich verzichte hier darauf die Bit-Operatoren erklären, da dies den Blogeintrag sprengen würde.
Für die Variablen diode... genügt es die werte 1 und 2 zu prüfen.
climbing wird mit true und false geprüft.
ladder... sind auch Variablen vom Typ Boolean und werden somit auch mit true und false geprüft.
Wir haben nun fünf Variablen, die jeweils zwei Werte annehmen können. Daraus ergeben sich 32 mögliche Kombinationen.
Ich muss hier fairer Weise eingestehen, dass ich die Funktion gekürzt habe. In meinem Framework werden hier elf Variablen verwendet, was über 2000 Prüfungsfälle ergibt. Ich komme da später darauf zurück.
Daraus ergibt sich folgende Tabelle:
diodeMidLeft,diodeTopLeft,ladderMidRight,ladderTopLeft,climbing 0,0,false,false,false
0,0,false,false,true
0,0,false,true,false
0,0,false,true,true
0,0,true,false,false
0,0,true,false,true
0,0,true,true,false
0,0,true,true,true
0,1,false,false,false
0,1,false,false,true
0,1,false,true,false
0,1,false,true,true
0,1,true,false,false
0,1,true,false,true
0,1,true,true,false
0,1,true,true,true
1,0,false,false,false
1,0,false,false,true
1,0,false,true,false
1,0,false,true,true
1,0,true,false,false
1,0,true,false,true
1,0,true,true,false
1,0,true,true,true
1,1,false,false,false
1,1,false,false,true
1,1,false,true,false
1,1,false,true,true
1,1,true,false,false
1,1,true,false,true
1,1,true,true,false
1,1,true,true,true
Jetzt haben wir alles, was wir brauchen um mit der eigentlichen Arbeit zu beginnen. Wir brauchen nur noch ein wenig Code:
- Wir packen die Prüfwerte in ein Array um sie besser verarbeiten zu können.
- Wir kopieren die Funktion A und benennen sie B. Diese wird dann optimiert.
- In einer Schleife rufen wir beide Funktionen auf und vergleichen die Ergebnisse
- Wir messen die Zeit, um zu sehen, ob die Optimierung erfolgreich war.
- var werte:Array = [
- [0,0,false,false,false],
- [0,0,false,false,true],
- [0,0,false,true,false],
- [0,0,false,true,true],
- [0,0,true,false,false],
- [0,0,true,false,true],
- [0,0,true,true,false],
- [0,0,true,true,true],
- [0,1,false,false,false],
- [0,1,false,false,true],
- [0,1,false,true,false],
- [0,1,false,true,true],
- [0,1,true,false,false],
- [0,1,true,false,true],
- [0,1,true,true,false],
- [0,1,true,true,true],
- [1,0,false,false,false],
- [1,0,false,false,true],
- [1,0,false,true,false],
- [1,0,false,true,true],
- [1,0,true,false,false],
- [1,0,true,false,true],
- [1,0,true,true,false],
- [1,0,true,true,true],
- [1,1,false,false,false],
- [1,1,false,false,true],
- [1,1,false,true,false],
- [1,1,false,true,true],
- [1,1,true,false,false],
- [1,1,true,false,true],
- [1,1,true,true,false],
- [1,1,true,true,true]
- ];
- function A(diodeMidLeft:int,diodeTopLeft:int,ladderMidRight:Boolean,ladderTopLeft:Boolean,climbing:Boolean):Boolean{
- if(
- (! (diodeMidLeft & 1) && ( !climbing || !ladderMidRight && climbing ) )
- ||
- (! (diodeTopLeft & 1) && ( !climbing || !ladderTopLeft && climbing ) )
- )
- return true;
- else
- return false;
- }
- function B(diodeMidLeft:int,diodeTopLeft:int,ladderMidRight:Boolean,ladderTopLeft:Boolean,climbing:Boolean):Boolean{
- if(
- (! (diodeMidLeft & 1) && ( !climbing || !ladderMidRight && climbing ) )
- ||
- (! (diodeTopLeft & 1) && ( !climbing || !ladderTopLeft && climbing ) )
- )
- return true;
- else
- return false;
- }
- for( var i:int = 0; i< werte.length;i++)
- trace( "case:",
- i,
- A(werte[i][0],werte[i][1],werte[i][2],werte[i][3],werte[i][4]) == B(werte[i][0],werte[i][1],werte[i][2],werte[i][3],werte[i][4])
- );
- var _start:int = getTimer();
- i = 0;
- while((i+=5)<1000000){
- A(werte[i%5][0],werte[(i+1)%5][1],werte[(i+2)%5][2],werte[(i+3)%5][3],werte[(i+4)%5][4] );
- }
- var _finish:int = getTimer();
- trace("ausführungsdauer Funktion A:",(_finish-_start));
- _start = getTimer();
- i = 0;
- while((i+=5)<1000000){
- B(werte[i%5][0],werte[(i+1)%5][1],werte[(i+2)%5][2],werte[(i+3)%5][3],werte[(i+4)%5][4] );
- }
- _finish = getTimer();
- trace("Ausführungsdauer Funktion B:",(_finish-_start));
Ich werde die eigentliche Optimierung im nächten Post zeigen, um die Länge dieses Eintrages nicht überzustrapazieren.
- 0 Comments



Your comment