Ist das Lesen der `length` - Eigenschaft ein array wirklich so teuer eine operation in JavaScript?
Ich immer davon ausgegangen, das Zwischenspeichern der Länge eines array in JavaScript ist eine gute Idee (vor allem im Zustand eines for
- Schleife) wegen der Kostspieligkeit der Berechnung der Länge eines Arrays.
Beispiel
for (var i = 0; i < arr.length; i++) { }
//vs
for (var i = 0, arrLength = arr.length; i < arrLength; i++) { }
Aber ich dachte, vielleicht ist die length
Eigenschaft wird nur aktualisiert, auf die Bildung und die änderung des Arrays. Daher Lesen es sollte nicht zu teuer sein, eine operation im Gegensatz zu Lesen Sie es in einer Variablen gespeichert (im Gegensatz zu anderen Methoden, die in anderen Sprachen benötigen, um im Speicher zu finden, das Ende von etwas, z.B. strlen()
in C).
Habe ich zwei Fragen. Ich bin auch daran interessiert, wie das funktioniert, also bitte nicht schlagen Sie mich mit der vorzeitige Optimierung stick.
Übernehmen die JavaScript-engines in den Browsern.
- Ist es von Vorteil, um die Zwischenspeicherung der
length
- Eigenschaft ein array in JavaScript? Ist dort viel stärker eingebunden in das Lesen einer lokalen Variablen über eine Objekt-Eigenschaft? - Ist die
length
Eigenschaft einfach verändert, die auf die Bildung und aufshift()
undpop()
Art Methoden, die nicht zurückkehren, ein neues array und sonst einfach als Ganzzahl gespeichert?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, hätte ich gesagt, es war teuer, aber dann schrieb ich einen kleinen test @ jsperf.com und zu meiner überraschung mit
i<array.length
tatsächlich schneller war, als in Chrome und in FF(4) ist es egal.Mein Verdacht ist, dass die Länge gespeichert als integer-Wert (Uint32). Aus dem ECMA-specs (262 ed. 5, Seite 121):
Puh! Ich weiß nicht, ob ich jemals wieder eine solche Sprache ...
Schließlich haben wir immer unsere guten alten rückständigen browser. Im IE (9, 8, 7), die Zwischenspeicherung, die Länge ist wirklich schneller. Einer der vielen Gründe mehr, nicht den IE nutzen, sage ich.
TL;DR:
Von dem, was ich sammeln können, es scheint wie die Länge des array wird intern zwischengespeichert (zumindest in V8)..
(Details? Lesen Sie weiter :))
So, diese Frage hat dinged in meinem Kopf herum, ein paar mal und ich habe beschlossen, zu erhalten, um die Wurzel des Problems (zumindest bei einer Umsetzung).
Graben rund um V8-Quelle ergab die JSArray Klasse.
Ich bin so eine Vermutung, dass der Typ der array-Elemente wird bestimmt, ob es schnell oder langsam. Ich habe unten ein bit-flag gesetzt
set_has_fast_elements
(set_bit_field2(bit_field2() | (1 << kHasFastElements))
), die ist, wo ich dachte, ich würde zeichnen, den Graben Linie, wie ich war auf der Suche im google-code und nicht die Quelle lokal.Nun, es scheint, dass alle Zeit alle Bedienung erfolgt auf dem array (das ist eine Kind-Klasse von
JSObject
ein Aufruf zuNormalizeElements()
, die ausgeführt wird, die folgenden:So, in Beantwortung Ihrer Fragen:
length
- Eigenschaft ein array (es sei denn, du tust etwas seltsam, dass zwingen würde, es zuslow
(ich bin mir nicht sicher, was diese Bedingungen sind) - nachdem das gesagt ist, werde ich höchstwahrscheinlich weiterhin cachelength
bis ich bekomme eine chance zu gehen durch alle OS-browser Implementierungen 😉length
Eigenschaft zu sein scheint, verändert nach alle Vorgang auf das Objekt ist.Edit:
Auf einer seitlichen Anmerkung scheint es, dass ein "leeres" array ist tatsächlich zugewiesen zu haben, die 4 Elemente:
Ich bin mir nicht sicher, wie viele Elemente das array wächst, sobald die Grenzen überschritten wurden - ich habe nicht Graben , dass tief 🙂
O(1)
für das einfügen.Einen anderen Satz von performance -tests. Die Schleife über ein array von Millionen von Zufallszahlen mit einer leeren Schleife.
In Chrom, die Schlaufen mit cached und non-cached-Längen Uhr so ziemlich die gleichen Zeiten, so bin ich vermute, es ist ein V8 Optimierung von cache die Länge.
In Safari und Firefox, werden die zwischengespeicherten Länge wurde konsequent über 2x schneller als die nicht-gecachte version.
Dieser Artikel untersucht, automatische Zwischenspeicherung, die in V8 und Chrom, durch bitten IRHydra für den generierten code:
Er fand, dass unter bestimmten Bedingungen manuell Zwischenspeichern der
.length
tatsächlich zusätzlichen Aufwand eher als die Verbesserung der Leistung!Aber trotzdem, diese Art von Mikro-Optimierung ist unwahrscheinlich, um einen spürbaren Gewinn für die Benutzer. Für Ihren Vorteil und für Ihre, konzentrieren Sie sich stattdessen auf code, ist klar zu Lesen, und mit guten Datenstrukturen und algorithmen in Ihrem code!
Vermeiden Sie vorzeitige Optimierung: Konzentrieren Sie sich auf eleganten code, bis ein performance-Problem entsteht. Nur dann, auf die Suche nach dem Engpass durch profiling und dann optimieren nur, dass ein Teil der code.
Nur eine Anmerkung:
Bei einigen Browsern (ich habe bemerkt, es in Safari, IE und Opera), können Sie bekommen einen Geschwindigkeitsschub durch die Zwischenspeicherung der Länge innerhalb der for-Schleife Erklärung:
Bearbeitete ich @KooiInc ist jsperf-test oben, um fügen Sie diesem Fall.
Darauf, dass Sie nicht davon ausgehen, dass dies wahr ist für alle Sammlungen durchsuchbar. Zum Beispiel das caching der Länge eines HTMLCollection 65% schneller in Chrome (Version 41) und 35% schneller in Firefox (Version 36).
http://jsperf.com/array-length-in-loop-dom
length
ist nicht statisch in eine HTMLCollection, es passt zu reflektieren Elemente aufeinander abgestimmt sind.