JavaScript 1.8.5 (ECMAScript 5) fügt einige interessante Methoden hinzu, die zukünftige Änderungen eines übergebenen Objekts mit unterschiedlichem Grad an Gründlichkeit verhindern:
Vermutlich geht es hauptsächlich darum, Fehler zu erkennen: Wenn Sie wissen, dass Sie ein Objekt nach einem bestimmten Punkt nicht mehr ändern möchten, können Sie es sperren, sodass ein Fehler ausgegeben wird, wenn Sie versehentlich versuchen, es später zu ändern. (Vorausgesetzt, Sie haben das getan "use strict";
.)
Meine Frage: Gibt es in modernen JS-Engines wie V8 einen Leistungsvorteil (z. B. schnellere Nachschlagen von Eigenschaften, reduzierter Speicherbedarf) beim Sperren von Objekten mit den oben genannten Methoden?
(Siehe auch John Resigs nette Erklärung - erwähnt jedoch nicht die Leistung.)
Antworten:
Es gibt keinen Leistungsunterschied seit mindestens Chrome 47.0.2526.80 (64-Bit).
Testing in Chrome 6.0.3359 on Mac OS 10.13.4 ----------------------------------------------- Test Ops/sec non-frozen object 106,825,468 ±1.08% fastest frozen object 106,176,323 ±1.04% fastest
Leistungstest (verfügbar unter http://jsperf.com/performance-frozen-object ):
const o1 = {a: 1}; const o2 = {a: 1}; Object.freeze(o2); // Non-frozen object: for(var key in o1); // Frozen object: for(var key in o2);
Update 30.10.2019 : Bei Chrome 78.0.3904 (64-Bit) gibt es keinen Leistungsunterschied.
Update 17.09.2019 : Bei Chrome 76.0.3809 (64-Bit) gibt es keinen Leistungsunterschied.
Update 03.05.2018 : Bei Chrome 66.0.3359 (64-Bit) gibt es keinen Leistungsunterschied.
Update 06.03.2017 : Bei Chrome 56.0.2924 (64-Bit) gibt es keinen Leistungsunterschied.
Update 13.12.2015 : Bei Chrome 47.0.2526.80 (64-Bit) gibt es keinen Leistungsunterschied.
Mit Chrome 34 schneidet ein eingefrorenes Objekt im Testfall von @ pimvdb etwas besser ab als ein nicht eingefrorenes (Ergebnisse unten). Der Unterschied scheint jedoch nicht groß genug zu sein, um die Verwendung dieser Technik für Leistungsvorteile zu rechtfertigen.
http://jsperf.com/performance-frozen-object
Testing in Chrome 34.0.1847.116 on OS X 10.9.2 ---------------------------------------------- Test Ops/sec non-frozen object 105,250,353 ±0.41% 3% slower frozen object 108,188,527 ±0.55% fastest
Das Ausführen der Testfälle von @ kangax zeigt, dass beide Versionen des Objekts ziemlich gleich funktionieren:
http://jsperf.com/performance-frozen-object-prop-access
Testing in Chrome 34.0.1847.116 on OS X 10.9.2 ---------------------------------------------- Test Ops/sec non-frozen object 832,133,923 ±0.26% fastest frozen object 832,501,726 ±0.28% fastest
http://jsperf.com/http-jsperf-com-performance-frozen-object-instanceof
Testing in Chrome 34.0.1847.116 on OS X 10.9.2 ---------------------------------------------- Test Ops/sec non-frozen object 378,464,917 ±0.42% fastest frozen object 378,705,082 ±0.24% fastest
quelle
something went wrong
Sie eine Kopie des Codes, den Sie für Ihren Anspruch getestet haben?Update: Da diese Antwort ursprünglich geschrieben wurde, wurde der Fehler in V8 behoben , der dieses Problem verursacht hat. Siehe die Antwort von Jan Molak für weitere Informationen.
In Google Chrome (also V8) iteriert ein eingefrorenes Objekt 98% langsamer als ein normales Objekt.
http://jsperf.com/performance-frozen-object
Wahrscheinlich liegt das daran, dass diese Funktionen relativ neu und wahrscheinlich noch nicht optimiert sind (aber das ist nur meine Vermutung, ich kenne den Grund ehrlich gesagt nicht).
Jedenfalls empfehle ich wirklich nicht, es für Leistungsvorteile zu verwenden, da dies anscheinend keinen Sinn ergibt.
* Der Code für den Test lautet:
var o1 = {a: 1}; var o2 = {a: 1}; Object.freeze(o2);
Test 1 (nicht gefrorenes Objekt):
for(var key in o1);
Test 2 (gefrorenes Objekt):
for(var key in o2);
quelle
Object.keys
sollte nicht langsamer . Ich bin damit einverstanden, dass es eher wie ein Fehler ist, da das Einfrieren kein Leistungseinbruch sein sollte. eher das Gegenteil.Theoretisch können Sie durch das Einfrieren eines Objekts stärkere Garantien für die Form eines Objekts abgeben.
Dies bedeutet, dass die VM die Speichergröße komprimieren kann.
Dies bedeutet, dass die VM die Suche nach Eigenschaften in der Prototypenkette optimieren kann.
Dies bedeutet, dass Live-Referenzen einfach nicht mehr live sind, da sich das Objekt nicht mehr ändern kann.
In der Praxis führen JavaScript-Engines diese aggressive Optimierung noch nicht durch.
quelle
null
. Eine andere Möglichkeit besteht darin, die gesamte Prototypenkette zusammen mitObject.prototype
(klingt beängstigend) einzufrieren .V8 hat Object.freeze zum 20. Juni 2013 und Object.seal und Object.preventExtensions zum 10. Dezember 2014 optimiert. Siehe Ausgabe https://code.google.com/p/chromium/issues/detail?id= 115960
quelle
Wenn Sie bei der Durchführung von Objekt interessiert sind Schöpfung (wörtliche vs gefrieren vs versiegelt vs
Immutable.Map
), habe ich einen erstellten Test auf jsPerf , dass aus zu überprüfen.Bisher hatte ich nur die Möglichkeit, es in Chrome 41 und Firefox 37 zu testen. In beiden Browsern dauert die Erstellung eines eingefrorenen oder versiegelten Objekts etwa dreimal länger als die Erstellung eines Literals - während die Leistung
Immutable.Map
etwa 50-mal schlechter ist als das wörtliche.quelle
Der einzige Grund, den ich für diese Methoden im Produktionscode sehe, ist, dass Sie aus Gründen der Integrität versiegelte oder eingefrorene Objekte haben können.
Zum Beispiel schreibe ich eine kleine Bibliothek, die einfach großartig funktioniert und Ihnen eine Reihe von Methoden in einem Objekt bietet, aber ich möchte nicht, dass Sie meine Eigenschaften oder Methoden ändern oder überschreiben. Ich sage nicht, dass ich Sie daran hindern kann, aber ich kann versuchen, Sie daran zu hindern, es aus Versehen zu tun, was vielleicht wichtiger ist.
Außerdem können diese Methoden in Umgebungen, die nichts über sie wissen, leicht "shim" werden, indem nur das ursprüngliche Objekt zurückgegeben wird. Natürlich hätte es dann keine Wirkung.
Ich sehe keine leistungsbezogenen Gründe dafür.
quelle