Du verwendest einen Internet Explorer in einer Version kleiner gleich 8. Dieser Browser wird nicht unterstützt. Bitte aktualisiere mindestens auf Version 9.
Patrick Saar - Artikel

Artikel

Patrick Saar

JavaScript Performance Tests

In meinem ersten Artikel stelle ich eine umfangreiche Studie über die Performance von JavaScript vor. Die Tests wurden in sechs Browsern der zu diesem Zeitpunkt neuesten Version durchgeführt. Zu jedem Bereich (Schleifen, Verzweigungen, Zugriffszeit, ...) gibt es Vergleiche der verschiedenen Programmierungsmöglichkeiten, die dazugehörigen Codezeilen und Zeitmessungen mit grafischen Auswertungen.
JavaScript Performance Tests

Heutzutage ist das Web nicht mehr nur eine Plattform um Inhalte und Daten zu präsentieren. Durch die Möglichkeiten, die uns HTML5 in Kombination mit CSS3 und JavaScript bieten, geht der Trend immer mehr zu systemunabhängigen Web-Applikationen für Smartphones, Tablets und Desktop-PCs. Dazu tragen auch die mächtigen JavaScript Frameworks, wie etwa jQuery, Prototype, MooTools, ... bei. Diese Web-Applikationen mit oder ohne solcher Frameworks bauen auf dem starken Einsatz von JavaScript auf. Deshalb wird die Performance dieser Skript-Sprache immer bedeutender.

Testverfahren

Es wurden verschiedene Aspekte der Programmierung von JavaScript untersucht. Dazu zählten die Untersuchung der Performance von Schleifen, String-Verkettung, Zugriff lokale - globale Variablen, Zugriff Variablen - Eigenschaften - Array Eintrag, Zugriff Klassenverschachtelungen, Vergleichsoperatoren von if-Bedingungen, Vergleich if - switch, Initialisierung von Arrays und von Objekten. Eine Wertung der Performance wurde mit jeweils vier Zeitmessungen pro Aspekt pro Programmiertechnik und deren Mittelwertbildung getroffen. Diese Messungen erfolgten in sechs Browsern. Den fünf Großen Firefox 17.0, Opera 12.11, Internet Explorer 9, Safari 5.1.7, Google Chrome 23.0 und einem eher unbekannten und nicht so weit verbreitetem Browser - dem Maxthon in der Version 3.4.5. Nebenbei gesagt ein interessanter Browser, der den Bekannten in nichts nachsteht. Bei jedem Test wurde auch ein Mittelwert über alle Durchschnitte der Zeitmessungen der einzelnen Browser angegeben. Am Ende jedes Bereiches werden diese Ergebnisse graphisch dargestellt. Es folgt eine Tabelle mit der maximalen Performanceverbesserung in Prozent zwischen der langsamsten und der schnellsten Ausführung pro Browser, aber auch als Mittelwert über alle.

Zeitmessung in JavaScript

Dieser Artikel behandelt wie gesagt die Performance von JavaScript. Es gibt Tipps zur Verbesserung dieser anhand von Messungen der Ausführungszeit verschiedener Code-Techniken. Um die Ausführungszeit eines beliebigen JavaScript Codes zu messen, speichern wir den aktuellen Timestamp, also die Zeit die seit dem 01.01.1970, 0:00 Uhr, bis heute vergangen ist, in der Variablen t_start. new Date() ist die Instanzierung des Date-Objekts und gibt uns das aktuelle Datum im Format Wochentag, Monat, Tag, Jahr, Uhrzeit, Zeitverschiebung zurück. Durch das Anhängen der Methode getTime() bekommen wir den Timestamp in Millisekunden als Integer-Wert.

var t_start, t_end;
t_start = new Date().getTime();
// Code, dessen Ausführungszeit wir messen wollen
t_end = new Date().getTime();
alert(t_end - t_start);

Nachdem der aktuelle Timestamp gespeichert worden ist, folgt unmittelbar der Code, dessen Ausführungszeit gemessen werden soll. Direkt am Ende des Codes wird dann wieder der Timestamp in der Variablen t_end gespeichert und die Differenz zwischen t_start und t_end mittels der alert-Methode ausgegeben. Somit bekommen wir die Zeit, die zur Ausführung des Codes benötigt wurde, in einer Messagebox angezeigt.

Flaschenhals der JavaScript Performance

Die größte Auswirkung auf die Performance hat der Zugriff auf das Document Object Model (DOM) und die Manipulation des DOMs. Man sollte immer versuchen die Anzahl der Zugriffe und Manipulationen so gering wie möglich zu halten. Sobald ein und dasselbe Objekt des DOMs in einem Skript mehr als einmal aufgerufen wird, sollte es in einer Variablen gespeichert werden.

Hier ein Beispiel wie es nicht gemacht werden sollte:

document.getElementById('box').style.border = '1px #333 solid';
var height = document.getElementById('box').offsetHeight;

In der ersten Zeile des Codes wird die CSS-Eigenschaft border des DOM Elements mit der ID box manipuliert. Die Variable h bekommt in der zweiten Zeile die Höhe des div-Elements, welche per CSS zugewiesen wurde, zugewiesen. Zwei Zugriffe auf dasselbe DOM Element also. Besser wir speichern das Objekt mit der ID box vorab in einer Variablen:

var doc = document.getElementById('box');
doc.style.border = '1px #333 solid';
var height = doc.offsetHeight;

In obigem Beispiel ist der Performancegewinn aufgrund von nur zwei Zugriffen marginal. Anders sieht es natürlich aus, wenn auf mehrere Elemente, z.B. über getElementsByTagName und Schleifen, zugegriffen wird.

Performance von Schleifen

Ein weiterer wichtiger Bestandteil von JavaScript auf dessen Performance ein Augenmerk gelegt werden sollte, sind Schleifen. Hier werden alle in JavaScript vorhandenen Schleifen (for, while, do und for in) untersucht. Vorweg kann man schon mal sagen, dass sich die ersten drei genannten Schleifen in ihrer Performance bei gleicher Programmiertechnik des Codes im Schleifenkopf und innerhalb der Schleife kaum unterscheiden. for in ist die langsamste Schleife und sollte deshalb nicht verwendet werden. Sie ist laut Zeitmessung im Mittel über alle Browser bis zu 47% langsamer als die Schnellste der anderen drei Schleifen. Sie wird zur Vollständigkeit am Ende dieses Abschnittes nochmals besprochen.

Ohne Gedanken an Performance Optimierungen schreibt man eine Schleife meistens so:

// Programmiertechnik 1
// for-Schleife
for (var i = 0; i < document.getElementsByTagName('div').length; i++) {
	text = document.getElementsByTagName('div')[i].innerHTML;
}

// while-Schleife
var i = 0;
while(i < document.getElementsByTagName('div').length) {
	text = document.getElementsByTagName('div')[i].innerHTML;
	i++;
}

// do-Schleife
var i = 0;
do {
	text = document.getElementsByTagName('div')[i].innerHTML;
	i++;
} while(i < document.getElementsByTagName('div').length)

Man geht alle div-Elemente durch beginnend bei 0 und endend bei document.getElementsByTagName('div').length - 1.

Für meine Zeitmessung habe ich nun per PHP 500.000 div-Elemente in einem PHP-Dokument erstellt. Es wird also auf document.getElementsByTagName('div').length in jedem Schleifendurchlauf, also 500.000 mal, zugegriffen. Wie im vorherigen Abschnitt beschrieben ist es daher besser diese Eigenschaft in einer Variable zu speichern. Es ergibt sich folgender verbesserter Code:

// Programmiertechnik 2
// for-Schleife
var len = document.getElementsByTagName('div').length;
for (var i = 0; i < len; i++) {
	text = document.getElementsByTagName('div')[i].innerHTML;
}

// while-Schleife
var len = document.getElementsByTagName('div').length;
var i = 0;
while(i < len) {
	text = document.getElementsByTagName('div')[i++].innerHTML;
}

// do-Schleife
var len = document.getElementsByTagName('div').length;
var i = 0;
do {
	text = document.getElementsByTagName('div')[i++].innerHTML;
} while(i < len)

Eine weitere Verbesserung liegt somit auf der Hand. Das DOM Objekt innerhalb der Schleife sollte natürlich auch in einer Variablen außerhalb der Schleife gespeichert werden:

// Programmiertechnik 3
// for-Schleife
var doc = document.getElementsByTagName('div');
var len = doc.length;
for (var i = 0; i < len; i++) {
	text = doc[i].innerHTML;
}

// while-Schleife
var doc = document.getElementsByTagName('div');
var len = doc.length;
var i = 0;
while(i < len) {
	text = doc[i++].innerHTML;
}

// do-Schleife
var doc = document.getElementsByTagName('div');
var len = doc.length;
var i = 0;
do {
	text = doc[i++].innerHTML;
} while(i < len)

Die letzte Verbesserung, wenn auch mit geringer Auswirkung in den modernen Browsern, ist folgende fortgeschrittenere Programmiertechnik. Dabei muss auf die Variable len nur noch einmal zugegriffen werden, der Iterator wird dekrementiert und die Schleife läuft gegen 0. Die Dekrementierung erfolgt in der For-Schleife in der Schleifen-Bedingung. Deshalb ist der Platz zwischen dem letzten Strichpunkt und der schließenden runden Klammer leer.

// Programmiertechnik 4
// for-Schleife
var doc = document.getElementsByTagName('div');
for (var i = doc.length; i--; ) {
	text = doc[i].innerHTML;
}

// while-Schleife
var doc = document.getElementsByTagName('div');
var i = doc.length;
while(i !== 0) {
	text = doc[--i].innerHTML;
}

// do-Schleife
var doc = document.getElementsByTagName('div');
var i = doc.length;
do {
	text = doc[--i].innerHTML;
} while(i !== 0)

Nun zur Auswertung der Zeitmessungen und des Verbesserungspotentials der vier vorgestellten Code-Techniken für die for-, while- und do-Schleife.

Zeitmessung JavaScript Performance-Tests for-Schleife
Verbesserungspotential For-Schleifen
Total
43,3% 74,0% 58,7% 51,1% 30,7% 39,8% 49,6%
Zeitmessung JavaScript Performance-Tests while-Schleife
Verbesserungspotential While-Schleifen
Total
46,8% 77,1% 66,6% 48,5% 31,0% 36,6% 51,4%
Zeitmessung JavaScript Performance-Tests do-Schleife
Verbesserungspotential Do-Schleifen
Total
52,3% 76,5% 59,8% 53,5% 32,3% 39,9% 52,5%

Programiertechnik 3 und 4 sind die Schnellsten und sollten daher vor allem in großen Schleifen zur Verwendung kommen. Ihre Ausführungszeit ist um bis zu ca. 75% geringer (je nach Browser). Die Prozentwerte in den Tabellen geben den maximalen Performancevorteil an. Je mehr Code in den Schleifen zusätzlich abgearbeitet werden muss, desto geringer fällt natürlich der prozentuale Vorteil der Schleifen-Optimierung aus.

Hier noch zwei Arten der Programmierung der for in-Schleife. Wie oben schon erwähnt, sollte der Einsatz dieser Schleife aufgrund ihrer schlechteren Performance vermieden werden.

// Programmiertechnik 1
// for in-Schleife
for (i in document.getElementsByTagName('div')) {
    text = document.getElementsByTagName('div')[i].innerHTML;
}

Die Technik für eine kürzere Ausführungszeit basiert wieder auf der Speicherung von DOM Objekten in einer Variablen.

// Programmiertechnik 2
// for in-Schleife
var doc = document.getElementsByTagName('div');
for (i in doc) {
    text = doc[i].innerHTML;
}
Zeitmessung JavaScript Performance-Tests for-in-Schleife
Verbesserungspotential For in-Schleifen
Total
29,8% 51,5% 46,3% 24,5% 13,7% 13,1% 29,7%

Performance der String-Verkettung in JavaScript

Die Verkettung von Strings ist ein weiterer wichtiger Aspekt in JavaScript. Normalerweise verknüpft man Strings mit dem "+"-Operator. Es gibt aber auch noch die von JavaScript bereitgestellte Methode concat() oder die Möglichkeit Strings mittels eines Buffer-Arrays und der Methode join() aneinanderzureihen. Welche Methode ist nun die Beste? Die Tests in den aktuellen Browsern (Stand 11.12.12) ergaben, dass die intuitivste Methode - der "+"-Operator - auch die Schnellste ist. Im Code-Fenster nochmals alle Programmiertechniken im Detail. Darunter die graphische Auswertung der Testergebnisse.

// String-Verkettung mit concat()
var temp0 = 'a';
var temp1 = 'b';
var temp2 = 'c';
var temp3 = 'd';
var temp4 = 'e';
for(var i = 0; i < 10000000; i++)
{
    text = temp0.concat(temp1.concat(temp2.concat(temp3.concat(temp4)))); 
}
 
// String-Verkettung mit join()
var temp = [];
temp[0] = 'a';
temp[1] = 'b';
temp[2] = 'c';
temp[3] = 'd';
temp[4] = 'e';
for(var i = 0; i < 10000000; i++)
{
    text = temp.join(''); 
}
 
// String-Verkettung mit +
for(var i = 0; i < 10000000; i++)
{
    text = 'a' + 'b' + 'c' + 'd' + 'e'; 
}
Zeitmessung JavaScript String Verkettung
Verbesserungspotential String-Verkettung
Total
99,4% 99,1% 53,7% 34,2% 99,4% 99,4% 80,9%

Unterschied der Zugriffszeit lokale - globale Variablen

Die Theorie sagt, auf lokale Variablen kann schneller zugegriffen werden als auf globale Variablen. Schuld ist der sogenannte Scope Chain. Der Scope Chain ist eine Unterteilung des JavaScript-Codes in Ebenen. Schauen wir uns das mal anhand eines Beispiel mit einer globalen und einer lokalen Variablen an.

// Scope Chain
var global = 1; // Ebene 0
function access_time() {
    var local = 1; // Ebene 1
    var nr;
    // Zugriff
    nr = global;
    nr = local;
}

Die Variable global steht hier ohne Kapselung direkt im Skript, also sozusagen auf Ebene 0. local dagegen ist von der Methode access_time gekapselt (Ebene 1). Bei Aufruf von local außerhalb der Methode ist der Rückgabewert undefined. Wird nun innerhalb der Methode access_time local aufgerufen, so bleibt man in derselben Ebene. Beim Aufruf von global hingegen, muss im Scope Chain auf Ebene 0 "zurückgegangen" werden. Dieser Vorgeng sollte daher laut Theorie länger dauern.

Die Ergebnisse des Tests bei 1.000.000.000 Zugriffe auf eine globale Variable und eine lokale Variable zeigt, dass bis auf den Opera und den Safari alle Browser die Theorie bestätigen. Im Chrome und im Maxthon ist allerdings nur ein minimaler Performanceunterschied messbar gewesen. Der größte Vorteil wird im Internet Explorer 9 erzielt.

Zeitmessung JavaScript Scope Chain
Performanceunterschied Zugriff lokale - globale Variable
Total
3,4% 0,0% 32,6% 0,0% 0,5% 0,1% 6,1%

Trotz der Nachteile im Opera und Safari bleibt ein Performancegewinn von 6,1%.

Unterschied der Zugriffszeit von Eigenschaften - Array Elementen - Variablen

Auf welchen Typ lässt sich am schnellsten zugreifen? Und wie sollte man Objekteigenschaften aufrufen? Diese Fragen werden in diesem Abschnitt beantwortet. Die Zeitmessung basiert auf 1.000.000.000 Aufrufen des jeweiligen Typs.

var text;
// Zugriff Typ 1 (Objekteigenschaft)
text = class1["str"];
// Zugriff Typ 2 (Objekteigenschaft)
text = class1.str;
// Zugriff Typ 3 (Array Element)
text = str[0];
// Zugriff Typ 4 (Variable)
text = str;
Zeitmessung JavaScript Zugriffszeit
Performanceunterschied Zugriffszeit Eigenschaften - Array Elemente - Variablen
Total
0,8% 1,7% 31,1% 90,3% 0,3% 0,0% 73,1%

Firefox, Opera, Chrome und Maxthon rufen alle Typen bis auf Messungenauigkeiten gleich schnell auf. Der Internet Explorer 9 bevorzugt Variablen. Im Safari sollte vor allem auf die erste Version des Eigenschftsaufruf verzichtet werden. Die Ausführungszeit bei 1.000.000.000 Zugriffen lag im Test bei über 25 Sekunden! Der Variablenaufruf ist im Apple-Browser wie auch im IE9 am schnellsten.

Unterschied der Zugriffszeit pro Objektverschachtelung

Der Scope Chain wirkt sich natürlich auch auf Objekteigenschaften aus. Auf class1.property kann schneller zugegriffen werden als auf class1.class2.class3.property. Sprich je mehr Punkte in einem solchen Ausdruck Verwendung finden, desto schlechter ist die Performance. Dieser Test soll nun zeigen um wie viele Millisekunden sich die Ausfürungszeit pro Verschachtelung (= neuem Punkt) bei 1.000.000.000 Zugriffen verlängert.

var text;
// Zugriff auf eine Objektverschachtelung
text = class1.str;
// Zugriff auf zwei Objektverschachtelungen
text = class1.class2.str;
// Zugriff auf drei Objektverschachtelungen
text = class1.class2.class3.str;
Zeitmessung JavaScript Zugriff auf Objekteigenschaften
Performanceunterschied Zugriffszeit pro Objektverschachtelung
Total
3,5% 46,4% 66,7% 50,0% 0,9% 0,8% 43,7%

Im Mittel verliert man pro zusätzlichem Punkt ca. 500 - 600 ms bei 1.000.000.000 Zugriffen. In kleinen Anwendungen sicher nicht messbar. In mächtigen Applikationen, wie z.B. Browsergames auf JavaScript-Basis, ein zu beachtender Faktor. Bei mehrmaligem Aufruf ein und derselben Eigenschaft ist eine Speicherung dieser in einer lokalen Variable evtl. am sinnvollsten.

Performance Vergleichsoperator in if-Bedingung - Strings

Es gibt in JavaScript wie auch z.B. in PHP zwei Gruppen von Vergleichsoperatoren. Den "ist gleich"-Operator in Form von == bzw. "ist ungleich" != und es gibt den "ist identisch"-Operator === bzw. "ist nicht identisch"-Operator !==. Beim zweiten angesprochenen Vergleichsoperator === müssen die verglichenen Werte nicht nur gleich sein, sondern auch von gleichem Datentyp. Beispiel: 1 === "1" ergibt false, da ein Integer-Wert mit einem Wert des Typs String verglichen wurde. Bei 1 == "1" lautet das Ergebnis allerdings true, da der Datentyp keine Rolle spielt. In der Theorie müsste der Vergleichsoperator === daher schneller sein. Bei ihm legt der Wert links des Operators den Datentyp fest. Es muss nur noch dieser Datentyp auf Übereinstimmung getestet werden, wo hingegen bei == alle Datentypen durchlaufen werden müssen. Der Vergleichsoperator === sollte natürlich nur verwendet werden, wenn man von der Gleichheit der Datentypen sicher ausgehen kann. Es sei denn man möchte nicht die Werte sondern die Datentypen überprüfen.

Der erste Test untersucht die Performance der Vergleichsoperatoren == und === für den Fall das Strings miteinander verglichen werden sollen. Wir haben folgende zwei Codes:

// Code 1 mit dem ==-Operator
var a = 'abc';
for(var i = 0; i < 100000000; i++)
{
    if(a == 'abc') {}   
}
// Code 2 mit dem ===-Operator
var a = 'abc';
for(var i = 0; i < 100000000; i++)
{
    if(a === 'abc') {}   
}

Anmerkung: Die for-Schleife dient nur zur Zeitmessung.

Die Ergebnisse in der Praxis unterscheiden sich für Vergleiche des Datentyps String erheblich von der Theorie. Der einzige Browser, der die Theorie deutlich bestätigt ist der Firefox. Im Safari hingegen ist die Performance des ===-Operators ca. 2,5 mal schlechter als die des ==-Operators. Alle anderen vier Browser zeigen nur einen sehr kleinen bis keinen Unterschied zwischen den beiden Operatoren in ihrer Geschwindigkeit. Im Gesamtergebnis ist die Schwäche des Safari für den ===-Operator nicht vom Performancevorteil des Firefox zu kompensieren. Bei JavaScript-Anwendungen, die in allen Browsern optimale Performance bieten sollen, sollte daher beim Vergleich des Datentyps String der ==-Operator bevorzugt werden.

JavaScript Zeitmessung String Vergleiche
Performanceunterschied Vergleichsoperator in if-Bedingung - Strings
Total
37,1% 0,0% 0,0% 0,0% 0,0% 1,8% 0,0%

Performance Vergleichsoperator in if-Bedingung - Integers

Jetzt der gleiche Test wie oben für den Vergleich von Werten des Datentyps Integer. Wir haben nun diese zwei Codeschnipsel:

// Code 1 mit dem ==-Operator
var a = 2;
for(var i = 0; i < 100000000; i++)
{
    if(a == 2) {}   
}
// Code 2 mit dem ===-Operator
var a = 2;
for(var i = 0; i < 100000000; i++)
{
    if(a === 2) {}   
}

Die Ergebnisse dieses Tests unterscheiden sich von den Ergebnissen für String-Vergleiche. Der Einsatz von === ist im Safari nur gering langsamer als der von ==. Der Firefox zeigt wiederum seine Bevorzugung gegenüber dem ===-Operator, so dass dieser Test zu Gunsten des "ist identisch"-Vergleichoperators ausfällt.

JavaScript Zeitmessung Integer Vergleiche
Performanceunterschied Vergleichsoperator in if-Bedingung - Strings
Total
48,6% 0,0% 0,0% 0,0% 0,0% 0,0% 6,0%

Performancevorteil des "ist identisch"-Operators liegt im Mittel bei 6,0%.

Performance Vergleichsoperator in if-Bedingung - Bool

Nun der letzte Test der Vergleichsoperatoren für den Datentyp Bool. Wir haben nun drei Code-Fragmente:

// Code 1
var a = true;
for(var i = 0; i < 100000000; i++)
{
    if(a) {}   
}
// Code 2 mit dem ==-Operator
for(var i = 0; i < 100000000; i++)
{
    if(a == true) {}   
}
// Code 3 mit dem ===-Operator
for(var i = 0; i < 100000000; i++)
{
    if(a === true) {}   
}

Bei Vergleichen von Werten des Datentyps bool, haben wir noch eine dritte Möglichkeit eine if-Bedingung zu formulieren, und zwar if(a) { ... }. Sehr schön zu schreiben, da sehr kurz. Und nicht nur das, dieser Test zeigt, dass die Benutzung des ==-Operators vermieden werden sollte. Er ist in allen Browsern bis auf statistische Abweichungen der Langsamste. Der Safari zeigt wiederum eine Schwäche für den "ist identisch"-Operator, so dass hier der kürzeste Code (Code 1) auch der effektivste gemittelt über alle Browser ist. In der Kürze liegt hier also die Würze. Die Tabelle spiegelt den prozentualen Unterschied vom ==-Operator zum Vergleichsoperator aus Code 1 wider.

Zeitmessung JavaScript Bool Vergleiche
Performanceunterschied Vergleichsoperator in if-Bedingung - Strings
Total
90,0% 2,3% 86,4% 44,7% 70,8% 70,9% 71,9%

Performancevergleich if - switch

Falls man in seinem Code eine längere Aneinanderreihung von if - else if - else-Bedingungen hat, und dabei diskrete Werte abgeprüft werden, sollte man über den Einsatz von switch - case nachdenken. Doch ab wie vielen Verzweigungen lohnt sich switch - case? Das soll in diesem Abschnitt geklärt werden. Zu diesem Zweck generiere ich mir mit einer Schleife vorab ein Array mit gleichverteilten Nullen und Einsen, um den Performanceunterschied von if - else if - else und switch - case im Fall von nur zwei Verzweigungen zu vergleichen.

var rand = [];
for (var i = 0; i < 10000000; i++) {
    rand[i] = i % 2;
}

Hier der Code der Verzweigungen dessen Ausführungszeit gemessen wurde:

// if - elseif
for(var i = 0; i < 10000000; i++)
{
    if(rand[i] === 0) { }
    else if(rand[i] === 1) { }   
}
// switch - case
for(var i = 0; i < 10000000; i++)
{
    switch(rand[i]) {
        case 0:
            break;
        case 1:
            break;
    }   
}

Es sollte nochmals beachtet werden, dass die hier zur Überprüfung stehenden Werte im Array gleichverteilt sind, und somit die Anordnung der Verzweigungen keine Rolle spielt. Sollte allerdings eine Nicht-Gleichverteilung der Werte vorliegen, deren Muster bekannt ist, so sollten die Werte, die öfter bei der Überprüfung true zurückgeben, auch in den ersten Verzweigungen behandelt werden. Dadurch müssen weniger Verzweigungen durchlaufen werden, und der Code ist insgesamt schneller.

Zurück zu diesem Test. Die Anzahl der Verzweigungen wurde nun stetig um 1 bis zum Wert 9 erhöht. Für neun Verzweigungen ergibt sich nun folgender Code. Erst das Array mit gleichverteilten Werten füllen:

var rand = [];
for (var i = 0; i < 10000000; i++) {
    rand[i] = i % 9;
}

Nun der Code dessen Performance gemessen wurde. Ich habe ihn mit ... abgekürzt um Schreibarbeit zu sparen.

// if - elseif
for(var i = 0; i < 10000000; i++)
{
    if(rand[i] === 0) { }
    else if(rand[i] === 1) { } 
 
    ...
      
    else if(rand[i] === 8) { }  
}
// switch - case
for(var i = 0; i < 10000000; i++)
{
    switch(rand[i]) {
        case 0:
            break;
        case 1:
            break;
         
        ...
 
        case 8:
            break;
    }   
}

Zu den Ergebnissen: Ab sieben Verzweigungen ist switch - case schneller als if - else if. Im Diagramm ist bei 0 mit dem Zählen der Verzweigungen begonnen worden, deshalb liegt in der graphischen Aufbereitung der Vorteil für switch - case ab Wert 6 auf der x-Achse.

JavaScript Zeitmessung Switch - If

Performance - Initialisierung eines Arrays

Als JavaScript-Neuling oder ohne Gedanken an Performance initialisiert man Arrays unbestimmter Länge gerne so.

var arr = new Array();

Die Initialisierung über das Literal ist allerdings in allen Browsern schneller.

var arr = [];

Arrays lassen sich am Anfang auch mit Werten vorbelegen. Egal welche der beiden Varianten verwendet wird, es ist in beiden möglich.

var arr1 = new Array('Hans', 'Peter');
var arr2 = ['Hans', 'Peter'];

Einzig eine feste Länge kann dem Array mittels Literal-Initalisierung nicht mitgegeben werden. Mit new Array() geht das bekanntlich so:

var arr = new Array(4); // 4 Elemente in arr

Nun zurück zur Performance. Zum Testen wurden folgende zwei Codes, welche im Endeffekt eine Matrix generieren (spielt aber für den Performancevergleich keine Rolle), verwendet.

// Initialisierung mit new Array()
var arr = new Array();
for(var i = 0; i < 5000000; i++)
{
    arr[i] = new Array();
}
// Initialisierung mit []
var arr = [];
for(var i = 0; i < 5000000; i++)
{
    arr[i] = [];
}

Im Firefox macht es keinen Unterschied wie Arrays initialisiert werden. In den übrigen Browsern allerdings schon. Performancevorteil gemittelt über alle Browser: 28,1%.

Zeitmessung JavaScript Array Initialisierung
Performance - Initialisierung eines Arrays
Total
0,3% 48,2% 8,7% 12,8% 42,7% 50,9% 28,1%

Performance - Initialisierung eines Objekts

Der letzte Test - Initialisierung eines Obejekts in JavaScript. Dies kann mit new Object() oder mit dem Literal {} geschehen. Wie bei Arrays ist das Literal die bessere Wahl. Folgender Code wurde zum Test verwendet:

// Initialisierung mit new Object()
var obj = [];
for(var i = 0; i < 5000000; i++)
{
    obj[i] = new Object();
}
// Initialisierung mit {}
var obj = [];
for(var i = 0; i < 5000000; i++)
{
    obj[i] = {};
}
JavaScript Zeitmessung Objekt Initialisierung
Performance - Initialisierung eines Objekts
Total
58,1% 22,2% 5,3% 20,9% 46,9% 51,5% 41,6%

Bei Objekt-Initalisierungen gibt es auch im Firefox Vorteile gegenüber der Benutzung des Literals. Performancevorteil gemittelt über alle Browser hier: 41,6%.

Schlusswort

Es gibt also eine Vielzahl an Möglichkeiten seinen Code zu verbessern. In den Referenzen kann man alle Codeschnipsel, die in dieser Studie zum Einsatz kamen, herunterladen und am eigenen Rechner mit Browsern seiner Wahl testen. Außerdem gibt es das umfassende Datenblatt mit allen Messungen als Excel-Datei.

Referenzen

Diese Seite verwendet Cookies um die beste Nutzerfreundlichkeit zu bieten. Falls Du auf der Seite weitersurfst, stimmst Du der Cookie-Nutzung zu.
Details Ok