2015-10-25 8 views
19

Mir ist aufgefallen, dass es beim Inkrementieren eines Zählers wesentlich langsamer ist, wenn der Wert des Zählers eine große Zahl ist. Ich habe es in Chrome, Firefox und IE11 versucht, alle zeigen eine schlechtere Leistung in großen Zahlen.Warum haben inkrementierende Operatoren (++) mit großen Zahlen eine schlechte Leistung?

See jsperf Test here (Code unten):

var count1 = 0; 
var count2 = new Date().getTime(); 
var count3 = 1e5; 
var count4 = 1e9; 
var count5 = 1e12; 
var count6 = 1e15; 

function getNum1() { 
    return ++count1; 
} 

function getNum2() { 
    return ++count2; 
} 

function getNum3() { 
    return ++count3; 
} 

function getNum4() { 
    return ++count4; 
} 

function getNum5() { 
    return ++count5; 
} 

function getNum6() { 
    return ++count6; 
} 

Warum geschehen ist das?

+0

Ich kann Ihre Ergebnisse in Firefox 41 nicht reproduzieren. Es behauptet, dass der kleine Datensatz 55% langsamer ist. –

+0

@ k-nut Das ist sehr seltsam, ich habe mit Firefox 41 getestet und sehe, dass der große Datensatz 45% langsamer ist. Konsequent so. – Malki

+0

Kann für Safari und Chrome unabhängig bestätigen, bis zu 2x schneller bei kleinen Zahlen. –

Antwort

28

Moderne JavaScript Laufzeiten und Compiler führen eine Optimierung namens SMI (Small Integers).

Alle Zahlen in JavaScript sind Fließkommazahlen mit doppelter Genauigkeit, für die Berechnungen relativ langsam sind. In der Praxis arbeiten wir jedoch in vielen Fällen (zum Beispiel in den meisten for Loops) mit Ganzzahlen.

Also - es ist sehr nützlich, Zahlen zu optimieren, um möglichst effiziente Berechnungen durchzuführen. Wenn der Motor beweisen kann, dass eine Zahl eine kleine ganze Zahl ist - wird es es als solches behandeln und alle Berechnungen durchführen, als ob die Zahl eine ganze Zahl ist.

Das Inkrementieren einer 32-Bit-Ganzzahl ist eine Einzelprozessoroperation und sehr billig. Sie erhalten also eine bessere Leistung.

+0

Siehe [diese Diashow] (http://v8-io12.appspot.com/index.html#34) für weitere Informationen, es ist etwas veraltet, aber immer noch ziemlich gut. –

+4

Beachten Sie, dass in vielen JavaScript-Engines diese Beschleunigung nur für * 31 * Bit-Ganzzahlen erreicht wird, da das MSB ein Tagging-Bit ist, das angibt, ob die Zahl als Ganzzahl oder als Verweis auf ein Doppelwort behandelt werden soll. – Joey

+0

@Joey richtig, diese Technik heißt Tagging. –

0

Diese 'große' Nummer, die Sie verwenden, ist jedoch sehr groß, ich wette, es ist der Unterschied zwischen der Verarbeitung einer 32-Bit-Menge und einer mehr als 32-Bit-Menge. Versuchen Sie eine Basis von 1.500.000,00 (unter 32 Bit signiert), 3.000.000.000 (unter 32 Bit vorzeichenlos) und 5.000.000.000 (über 32 Bit).

+0

JavaScript-Nummern sind immer 64-Bit Fließkomma: http://www.w3schools.com/js/js_numbers.asp –

+1

@Oleg das ist egal, was für Optimierungen a Compiler könnte ausführen, wenn es eine Zahl beweisen kann, ist tatsächlich ein 32bit int. –

+1

Tatsächlich optimieren alle JS-Engines, die ich kenne, dies - die Optimierung heißt SMI (steht für kleine ganze Zahlen). –