2009-08-11 2 views
1

Ich habe gerade ein Video von Nicholas Zakas of Yahoo gesehen, in dem GoogleTalks über die Beschleunigung Ihrer Website spricht. Eines der Dinge, die er erwähnte, war Schleifen in umgekehrter Reihenfolge, um einen von zwei Vergleichen zu überspringen:JS Schleifen und Füllen von Array. Welche ist schneller?

Und er sagte, um JS Bibliotheken Implementierungen von for each zu vermeiden. Nur zum Spaß dachte ich, ich würde es ausprobieren. Stellt sich heraus, er hat sich geirrt.

var array1 = new Array(); 
var array2 = new Array(); 
var start = 0; 
var finished = 0; 
start = (new Date).getTime(); 
$("#newDivTest").children().each(function(i){ 
    array1[i] = $(this).get(0).id; 
}); 
finished = (new Date).getTime() - start; 
alert(finished); 

start = (new Date).getTime(); 
var len = $("#newDivTest").children().length; 

for (i = len; i--;) { 
    array2[i] = $(this).get(0).id; 
} 
finished = (new Date).getTime() - start; 
alert(finished); 

newDivTest hält 1000 leer divs mit einer ID auf "0" ab und zu "999" nach oben. Eine andere Anmerkung ist, dass $(this).get(0).id ist etwa 3 mal schneller als $(this).attr("id") aus irgendeinem Grund weiß jemand warum?

Für FF3.5 sind die Ergebnisse "7" und "45", IE7 gibt "30" und "45", Chrome2 gibt "4" und "17", Opera10 gibt "16" und "16" und schließlich gibt Safari4 "4" und "16".

So scheint es der Ansatz, gegen den Nicholas am härtesten ist, ist eigentlich der schnellere in fast allen Fällen.

Ich bin nicht schlau genug zu wissen, was hinter den Kulissen für jQuerys each() -Methode passiert, aber es muss etwas richtig machen ... richtig?

+1

sollte dies nicht funktionieren, weil in „array2 [i] = $ (dies) .get (0) .id; " Dies ist ein globaler Bereich, kein div. –

+0

Die Existenz dieser Art von Frage ärgert mich kein Ende. Wie rückwärts, dass der Programmierer nach 50 Jahren Compiler-Technologie diese Mikro-Optimierungen noch manuell durchführen muss! –

Antwort

7

Ein Fehler in Ihrem Setup ist, dass Ihr zweiter Test nicht wirklich funktioniert. Sie schrieb:

for (i = len; i--;) { 
    array2[i] = $(this).get(0).id; 
} 

Aber this dort nicht definiert ist, so dass der gesamte Vorgang fehlschlagen. Du müsstest, wie etwas zu tun:

var children = $("#newDivTest").children(); 
for (i = children.length; i--;) { 
    array2[i] = children.get(i).id; 
} 

Und das wird zu einem dringenderes Problem als Performance: Obwohl Anrufe zu so etwas wie jQuery .each() Funktion in den Nachspielfunktionsaufrufen haben zur Folge (und der damit verbundenen zusätzlichen Aufwand), machen sie es auch viel einfacher, auszudrücken, was der Code tun soll.

Zitat Michael Jackson: "Die erste Regel der Programmoptimierung: Tun Sie es nicht. Die zweite Regel der Programmoptimierung (nur für Experten!): Tun Sie es noch nicht."

+0

Ich kann nicht glauben, dass ich das verpasst habe ... meine Güte. Wenn man es umschreibt, wird der zweite tatsächlich schneller. Danke, dass du es trotzdem erwähnt hast (: – peirix

1

Sind Ihre Tests nicht anders? Im zweiten Test this ist nicht das gleiche wie das erste.

1

Slightly Off-Topic und nicht eine direkte Antwort auf Ihre wichtigste Frage aber, jQuery jede Methode ist wie so implementiert (jQuery 1.3.2)

jQuery.extend({ 

     /* ... Code taken out for brevity ... */ 

    // args is for internal usage only 
    each: function(object, callback, args) { 
     var name, i = 0, length = object.length; 

     if (args) { 
      if (length === undefined) { 
       for (name in object) 
        if (callback.apply(object[ name ], args) === false) 
         break; 
      } else 
       for (; i < length;) 
        if (callback.apply(object[ i++ ], args) === false) 
         break; 

     // A special, fast, case for the most common use of each 
     } else { 
      if (length === undefined) { 
       for (name in object) 
        if (callback.call(object[ name ], name, object[ name ]) === false) 
         break; 
      } else 
       for (var value = object[0]; 
        i < length && callback.call(value, i, value) !== false; value = object[++i]){} 
     } 

     return object; 
    } 

     /* ... Code taken out for brevity ... */ 

     ); 

wie Sie sehen können, eine callback Funktion wird auf jede Anwendung Eigentum von object. die jQuery Objekt eine Länge Eigenschaft hat, so dass die folgende Schleife definiert wird zuführen (im allgemeinen kein args geliefert werden)

for (var value = object[0]; i < length && callback.call(value, i, value) !== false; value = object[++i]){} 

in jeder Iteration wird die Callback-Funktion, um den Umfang der Kettenlänge um 1 zu erhöhen, wird länger dauern, was zu Lösen Sie den Verweis auf die Objekteigenschaft auf.

1

Ich stelle fest, dass Ihre Frage lautet "JS Schleifen und Befüllen Array. Was ist schneller?", Aber Ihre Beispiele testen tatsächlich die Geschwindigkeit der verschiedenen Selektoren von JQuery, richtig?Sie könnten bei der Prüfung interessiert sein: "JS Looping und bevölkern Array, das schneller ist?" http://mootools.net/slickspeed/

Was finden Sie hier: http://blogs.oracle.com/greimer/resource/loop-test.html

+0

Nein, mein Beispiel testet nur die Geschwindigkeit von jQuerys 'each()' vs. native JS 'für (i = len; i -;) {})' ... – peirix

Verwandte Themen