Vom Overhead der Kommunikation …
Grundidee
Auf der Suche nach Flaschenhälsen und Ineffizienz in einem meiner Codes fiel mir Folgendes auf:
1. es gibt eine einfach Berechnung, die immer wieder verwendet und häufig aufgerufen wird
2. Auslagerung dieser Berechnung in eine statische Methode einer Bibliothek macht also Sinn
Dies führt also zu einem Aufruf der Art Bibliothek.Mathe.degToRad (x) statt die Lösung des Problems jedes Mal aufs Neue an Ort und Stelle zu formulieren. Kurz: der Gedanke der Wiederverwertung. Aufbauend darauf der Gedanke der objektorientierten Programmierung, welche einen jede Komplexität beherrschen läßt.
Problem 1 – Instanztiefe
Mit jeder Instanztiefe wird der Aufruf brutal langsamer. Sprich wenn wir die Methode endlos von Instanz zu Kind-Instanz verlinken, dann wird diese Methode niemals fertig. (!) Das klingt jetzt trivial, aber das ist es nicht: die Instanz-Struktur beeinflußt im hohen Maße die Geschwindigkeit einer Methode. Sicher kann man an dieser Stelle dafür sorgen, daß man flach in der Instanzstuktur bleibt (egoistische Diktator-Instanz) …, aber wer will denn das? Widerspricht das nicht dem objektorientierten Streben eines jeden, der Komplexität durch Greifbarkeit und Analogien zu meistern versucht? Oder wiederverwendbare Bibliotheken anzulegen, die in Grenzfällen dafür sorgen, daß sie gar nicht nutzbar sind aufgrund ihrer Kapselung und dem damit verbundenen “Kommunikations-Overhead” …
Problem 2 – statische Fremdmethoden (Bibliotheken)
Der Geschwindigkeitseinbruch bei statischen Aufrufen schon bei Methoden 1. Ordnung ist fast unglaublich. Es macht einen Riesenunterschied, ob ich 10.000.000 Mal eine eigene Methode aufrufe oder eine statische Fremdmethode.
Ein Beispiel:
10.000.000 Mal 1 * 1 berechnen = 49 ms
10.000.000 Mal eine statische Methode aus einer Bibliothek aufrufen, die 1 * 1 berechnet = 2534 ms (um den Faktor 50 langsamer!)
Jetzt stellen wir uns die Berechnung mal komplizierter vor: in der Berechnung wird zum Beispiel die Konstante PI aus der AS3-Standardklasse Math benutzt und schon sind wir wieder eine Schritt weiter im Sumpf des Zeitverbratens …
Bedeutung
Es ist logisch, daß 1 * 1 schneller ist als pow (1, 2), weil beim Methodenaufruf noch diverse Checks durchgeführt werden, die wir in unserem trivialen Fall gar nicht benötigen. Bedeutend ist aber, das jeder Versuch der Kapselung Geschwindigkeit kostet … – und zwar in einem Maße, daß man gleich wieder geneigt ist, stupide Kilometer-Codes zu erzeugen, wo alles flach hintereinander abgearbeitet wird. Ohne Methodenaufrufe und Kapselung …
Vielleicht nichts, was einen Programmierer überraschen sollte. Mich überraschte nur, daß dies gleich 50% der kompletten Rechenzeit beansprucht. Vielleicht betrifft dies auch nur AS3 & Flash so extrem? Abhängig vom Grad der Kompilierung? Oder bin ich einfach zu objektorientiert? Vielleicht übertreibe ich auch maßlos? Entweder man programmiert also wie eine Maschine (alles hintereinander weg) oder man hat einen Kompiler, der die Nachteile der Objektorientierung ausbügeln kann. Aber ist der Kompiler zur Laufzeit wirklich noch relevant? Wenn das Programm im Speicher ist, dann gibt es doch eigentlich nichts mehr zu optimieren … – und trotzdem kleckert die Zeit weg, als würde man eine Wand dressieren wollen.
Code
Hier ein kurzer Prüfcode, der das Problem konkret macht für die, die es interessiert …
Das Ergebnis ist einfach, daß mit steigender Tiefe die Abarbeitungszeit für die gleiche Arbeit immer weiter ansteigt. Man könnte meinen, daß dies durch die Prüfung (oChild ?) passiert: sicher verbraucht dies Rechenzeit, aber nicht 25% (variiert natürlich mit dem Rechenaufwand, den eine Methode selber verursacht) mit jeder weiteren Instanztiefe. Wenn ich darüber nachdenke wohl ein eher schlechtes Beispiel, aber wer das selbst mal ausprobiert, wird sehen, wo es brennt …

Actionscript 2 & 3: Die Evolution von “for..in”?
Folgender Code soll das Problem veranschaulichen:
var oTest:Object = new Object ();
for (var sY:String = '', uX:Number = 0; uX < 10; uX ++) {
sY = String.fromCharCode (uX + 65);
oTest[sY] = uX;
trace (sY + " = " + uX);
}
trace ("-------- for in ----------->");
for (var sI:String in oTest) {
trace (sI + " = " + oTest[sI]);
}
Dieser Code in AS2 kompiliert führt zu folgendem Ergebnis:
A = 0
B = 1
C = 2
D = 3
E = 4
F = 5
G = 6
H = 7
I = 8
J = 9
——– for in ———–>
J = 9
I = 8
H = 7
G = 6
F = 5
E = 4
D = 3
C = 2
B = 1
A = 0
Das Erstellen von Eigenschaften fuer ein Objekt wird intern also in einem Stack geführt, wodurch die Reihenfolge erhalten bleibt (natürlich gedreht wie es bei einem Stack erwartbar ist).
Kompiliert man den selben Code in AS3, dann ist das Ergebnis:
A = 0
B = 1
C = 2
D = 3
E = 4
F = 5
G = 6
H = 7
I = 8
J = 9
——– for in ———–>
H = 7
C = 2
I = 8
D = 3
J = 9
E = 4
F = 5
A = 0
G = 6
B = 1
Welchem Schema folgt die Ausgabe der Methoden nun? Wohl keinem. Sicherlich ist dies kein großes Problem, wenn man denn weiß, daß es so ist. Und siehe da, es wird sogar in der Doku erwähnt:
Object properties are not kept in any particular order, so properties may appear in a seemingly random order.
Jemand eine Idee, warum das so sein muß? Denn nur durch das Stack-Verhalten bei der Zuweisung von Objekteigenschaften kann man die Reihenfolge bewahren. Nun muß man Arrays benutzen, die Objekte enthalten, welche wiederrum Eigenschaften haben, die abgefragt werden müssen. Um ein bestimmtes Objekt mit einer bestimmten Eigenschaft zu erhalten, ist also eine Suche über alles nötig, was bisher durch einen Direktverweis anhand des Eigenschaftsnamen möglich war. Warum muß das so sein? Wo PHP & Co das Durchlaufen von Objekteigenschaften auch in definierter Ordnung realisieren können …
Bug || Feature?
Actionscript 2 & 3: Die Evolution von “for..in”?
Folgender Code soll das Problem veranschaulichen:
var oTest:Object = new Object ();
for (var sY:String = '', uX:Number = 0; uX < 10; uX ++) {
sY = String.fromCharCode (uX + 65);
oTest[sY] = uX;
trace (sY + " = " + uX);
}
trace ("-------- for in ----------->");
for (var sI:String in oTest) {
trace (sI + " = " + oTest[sI]);
}
Dieser Code in AS2 kompiliert führt zu folgendem Ergebnis:
A = 0
B = 1
C = 2
D = 3
E = 4
F = 5
G = 6
H = 7
I = 8
J = 9
——– for in ———–>
J = 9
I = 8
H = 7
G = 6
F = 5
E = 4
D = 3
C = 2
B = 1
A = 0
Das Erstellen von Eigenschaften fuer ein Objekt wird intern also in einem Stack geführt, wodurch die Reihenfolge erhalten bleibt (natürlich gedreht wie es bei einem Stack erwartbar ist).
Kompiliert man den selben Code in AS3, dann ist das Ergebnis:
A = 0
B = 1
C = 2
D = 3
E = 4
F = 5
G = 6
H = 7
I = 8
J = 9
——– for in ———–>
H = 7
C = 2
I = 8
D = 3
J = 9
E = 4
F = 5
A = 0
G = 6
B = 1
Welchem Schema folgt die Ausgabe der Methoden nun? Wohl keinem. Sicherlich ist dies kein großes Problem, wenn man denn weiß, daß es so ist. Und siehe da, es wird sogar in der Doku erwähnt:
Object properties are not kept in any particular order, so properties may appear in a seemingly random order.
Jemand eine Idee, warum das so sein muß? Denn nur durch das Stack-Verhalten bei der Zuweisung von Objekteigenschaften kann man die Reihenfolge bewahren. Nun muß man Arrays benutzen, die Objekte enthalten, welche wiederrum Eigenschaften haben, die abgefragt werden müssen. Um ein bestimmtes Objekt mit einer bestimmten Eigenschaft zu erhalten, ist also eine Suche über alles nötig, was bisher durch einen Direktverweis anhand des Eigenschaftsnamen möglich war. Warum muß das so sein? Wo PHP & Co das Durchlaufen von Objekteigenschaften auch in definierter Ordnung realisieren können …
Bug || Feature?
Deterministische Zombies
Da kommt man Montag morgen rein mit allen Aufgaben für den Tag im Kopf und klaren Zielen …
“Thomas, Kyle ist nicht erreichbar ….”
Einer unserer Server, “Kyle” genannt, ist nicht mehr erreichbar. Was war geschehen? Von überall pingt man zum gleichen Ziel, doch keine Antwort. Im Postfach dann die Benachrichtigung vom Provider des Servers:
“Ihr Server mit der im Betreff genannten IP-Adresse hat Scans auf andere Server im Internet ausgeführt.
Dabei wurden erhebliche Netzwerkressourcen beansprucht und folglich ein Segment unseres Netzwerkes stark negativ beeinträchtigt.
Ihr Server wurde deshalb vorsorglich deaktiviert.”
Argh! Vorsorglich? Argh! Schnellstmöglich mußte der Server wieder ans Netz. An all die Kunden denkend, die uns zurecht gleich die Tür einrennen würden. Artig das Standardprozedere des Providers für diesen Fall befolgend: eine Remote-Console beantragt, um auf dem Server offline kontrollieren zu können, was geschehen war.
Die Logs durchforstend nach Auffälligkeiten – auf der Suche nach einem Zeichen einer möglichen Kompromittierung. Auf den ersten Blick schien alles normal zu sein. Auch keine Traffic-Explosion war zu verzeichnen, ganz im Gegenteil: der Server war auf den ersten Blick so was von artig und unterfordert. Einen Kollegen benachrichtigend, Andre, um mit mir zusammen nach Spuren dieses Supergaus (Derartiges sollte doch Spuren hinterlassen?) zu suchen. Und siehe da, wir fanden seltsame Skript, die nicht zuzuordnen waren. Mehr als nur eins …
STASI Drone über Rostock
Habe eine Kamera auf meine “Easystar” (RC-Flugzeug) montiert und war wieder auf Spionagemission. Dies sind die ersten Aufnahmen, welche leider verwackelt, weil hier Windstärke 6 herrschte und ich die ganze Zeit mit Vollgas fliegen mußte, um nicht im Kanal zu landen. Im Youtube-Video ist ein kurzer Ausschnitt (komplette Video ist 18 Minuten lang) von wilden Turns beim mir vorm Block bei mächtig Wind und anschließender Punktlandung zu sehen. Man achte auf das Gras kurz vor der Landung.
Vor Kurzem überquerte ein Modellflugzeug in 95 Stunden mit nur 2,8 Litern Sprit den Atlantik. Völlig autark steuerte es sich selbst per GPS und diverser Telemetrie-Daten von Neufundland bist nach England. Realisiert mit handelsüblicher Modellbautechnik von 5 US-Rentern. Und jetzt stelle man sich die Möglichkeiten dieser Technik mit einem unbegrenzten Regierungsetat vor … :)
Nachtrag: ein weiteres Video bei wesentlich ruhigerem Wetter vor Rostock Port. Beinahe baden gegangen, weil der Motor mitten auf dem Wasser ausging. Gerade so bis ins Schilff geschafft.
STASI Drone über Rostock
Habe eine Kamera auf meine “Easystar” (RC-Flugzeug) montiert und war wieder auf Spionagemission. Dies sind die ersten Aufnahmen, welche leider verwackelt, weil hier Windstärke 6 herrschte und ich die ganze Zeit mit Vollgas fliegen mußte, um nicht im Kanal zu landen. Im Youtube-Video ist ein kurzer Ausschnitt (komplette Video ist 18 Minuten lang) von wilden Turns beim mir vorm Block bei mächtig Wind und anschließender Punktlandung zu sehen. Man achte auf das Gras kurz vor der Landung.
Vor Kurzem überquerte ein Modellflugzeug in 95 Stunden mit nur 2,8 Litern Sprit den Atlantik. Völlig autark steuerte es sich selbst per GPS und diverser Telemetrie-Daten von Neufundland bist nach England. Realisiert mit handelsüblicher Modellbautechnik von 5 US-Rentern. Und jetzt stelle man sich die Möglichkeiten dieser Technik mit einem unbegrenzten Regierungsetat vor … :)
Nachtrag: ein weiteres Video bei wesentlich ruhigerem Wetter vor Rostock Port. Beinahe baden gegangen, weil der Motor mitten auf dem Wasser ausging. Gerade so bis ins Schilff geschafft.
-
eidberger
26 Beiträge
23 Kommentare
(seit 02/2007) -
Links
-
Blog Abo
