dass ich vergessen habe rechtzeitig fuer Nancy die gewuenschten Artikel aus Deutschland einzukaufen, ist doch prompt mein Auto liegengeblieben – mit Batterie leer und so. Also eine Stunde im Auto warten (kalt) und dann eine Stunde durch die Gegend fahren (teuer).
Archive for November, 2006
You are currently browsing the Martin en Neukoelln archives for November, 2006.
Warum einfacher manchmal langsamer ist
Aus dem aktuellem Projekt an dem wir gerade arbeiten (geheim, geheim) will ich nun zum ersten mal eine Erfahrung mitteilen. Da wir viel mit JavaScript arbeiten, wird es hier diesmal ausschliesslich um diese Skriptsprache gehen. Doch worum geht es eigentlich?
Nachdem wir eine Funktion fertig implementiert hatten und im Prinzip damit zufrieden waren, stellten wir fest, dass sich dieser Applikationsteil erstaunlich langsam anfuehlt. Da wir aber nicht schon zu einem solch fruehen Zeitpunkt diesen Fakt ignorieren wollen, machten wir uns auf die Suche.
Erster Anlaufpunkt war dabei das Profiling des Venkman JavaScript Debuggers. Diese gab uns die Moeglichkeit das Profiling unserer Applikation zu einem bestimmten Zeitpunkt zu aktivieren und danach wieder abzuschalten – die Integration erfordert dabei keinelei Konfiguration bzw. Aenderungen am Quelltext. Die Profilingdaten haben wir dann abgespeichert und mit einem normalen Texeditor analysiert und entsprechende Broken herausgesucht. Interessant sind dabei vor allem Codestellen, die viel Zeit verbrauchen, dabei aber nur wenige Aufrufe haben. Hier ein Beispiel fuer einen Auszug aus den Profilingdaten:
demo.js: 750 – 2500 milliseconds
Function Name: prepareData (Lines 3 – 20)
Total Calls: 1 (max recurse 0)
Total Time: 1734.39 (min/max/avg 1734.39/1734.39/1734.39)
Time (ex. calls): 187.5 (min/max/avg 187.5/187.5/187.5)
Man kann gut erkennen, dass ein einziger Aufruf dabei ca 1800 Milisekunden verbraet. Als wir nun die entsprechende Stelle in unserem Code gefunden hatten, stellte sich die Frage wie man das besser machen kann. Denn die Codezeile war wirklich einfach und sah ungefaehr so aus:
result = data.pluck(“name”).uniq();
Die Funktion pluck() und uniq() werden dabei von der Prototype Bibliothek zur Verfuegung gestellt. Die pluck Funktion geht dabei ueber ein Array aus Hashes und sammelt alle Werte die den Schluessel haben, der als Parameter angegeben ist – in diesem Fall der Key name. Die Funktion uniq() macht genau das was ihr Name sagt und entfernt doppelte Element aus einem Array. Diese Kombination ist genau dann interessant, wenn man aus einer Ergebnismenge den Wertebereich bestimmen moechte. Zum Beispiel erhalet man von einer Funktion eine Liste von Objetek zurueck und moechte nun den Wertebereich einer bestimmten Eigenschaft extrahieren. In einem solchen Fall muesste man so vorgehen, zumal die Kombination dieser beiden Funktionen sehr angenehm aussieht.
Doch dabei gibt es ein Problem. Diese Funktionen sind beide sehr zeitafuwaendig und erzeugten bei uns damit ein Problem. Mathias kam dabei auf die Idee statt alle Werte zu extrahieren, mit einem Hash zu arbeiten (genial!). Daraus wurde dann der Folgende Code:
function uniqFromHashArray(data, key){
var tmp = $H({});
data.each(function(v){
tmp[v.name]= “”
});
return tmp.keys();
}
Und man mag es nicht glauben, aber dieser Code war ungemein performanter. Der entscheidende Vorteil liegt darin, dass die Zugriffe auf das Hash immer konstant sind. Da man die Werte als Schluessel fuer das neue Hash nimmt, werden doppelte Werte automatisch unterbunden. Dadurch erspart man sich das haeufige iterieren ueber das Array.
Den Code nocheinmal als Vergleich zusammengefasst ergibt:
function prototypeUniqKeys(data){
return data.pluck(“name”).uniq();
}
function hashUniqKeys(data){
var tmp = $H({});
data.each(function(v){
tmp[v.name]= “”
});
return tmp.keys();
}
var data = prepareData(10000);
var b,e;
b = new Date();
prototypeUniqKeys(data);
e = new Date();
b = new Date();
hashUniqKeys(data);
e = new Date();
Mit dem folgenden relativ konstanten Ergebnis fuer 10000 Datensaetze ca. 1100 ms fuer die Prototype Variante und ca. 110 ms – Sprich dieser Codeteil wurde um den Faktor 10 beschleunigt.
Daraus ergibt sich die Schlussfolgerung, dass zwar die Bibliotheksfunktionen besser handhabbar sind, aber manchmal die Aneinanderreihung von derartiger Funktionalitaet ein System verlangsamen kann. Daher lieber fruehzeitig Profiling der Anwendung betreiben und langsame Codestellen im Auge behalten. Fuer all die, die das zu Hause ausprobieren wollen, habe ich diesen Test in ein wenig Code und ein Archiv gegossen, dass man sich hierherunterladen kann.
Neues aus dem Projektraum III
- Der Kaffee ist nicht stark, ich kann den Loeffel noch 2cm unter der Oberflaeche sehen!
- Und weiter kriegst du ih nicht reingedrueckt?
One for the night – Text Message Breakup
Danke an Jan fuer den Hinweis. Ein absolutes Must See!!!
Neues aus dem Projektraum II
Kann man eigentlich Klaus auf Carsten casten?
Neues aus dem Projektraum I
Die Eclipsegoettin hat wieder zugeschlagen – Inkonsistenzia
SAP Netweaver Server macht mich verrueckt!! – Deswegen verkauft SAP den nur an Oracle.



