Bevor ich JavaScript verwendete, war ich bereits recht vertraut mit C, C++ und C#. Wie bei vielen C/C++-Entwicklern war mein erster Eindruck von JavaScript kein guter. In diesem Artikel wird hauptsächlich die Entwicklung und Leistungsanalyse von JavaScript-Arrays vorgestellt. In diesem Artikel geht es mehr um Speicher, Optimierung, Syntaxunterschiede, Leistung und aktuelle Entwicklungen. Freunde in Not können darauf verweisen, ich hoffe, es kann allen helfen.
Array ist einer der Hauptgründe. JavaScript-Arrays sind nicht zusammenhängend und werden wie Hash-Maps oder Wörterbücher implementiert. Meiner Meinung nach handelt es sich hier um eine B-Level-Sprache, und die Array-Implementierung ist einfach nicht angemessen. Seitdem haben sich JavaScript und mein Verständnis davon stark verändert.
Warum JavaScript-Arrays keine echten Arrays sind
Bevor wir über JavaScript sprechen, sprechen wir zunächst darüber, was Array ist.
Ein Array ist eine zusammenhängende Folge von Speicherorten, die zur Speicherung eines bestimmten Werts verwendet werden. Es ist wichtig, die Betonung „kontinuierlich“ (oder zusammenhängend) zu beachten.
Die obige Abbildung zeigt, wie Arrays im Speicher gespeichert werden. Dieses Array enthält 4 Elemente, jedes Element ist 4 Bytes groß. Insgesamt belegt es 16 Byte Speicherbereich.
Angenommen, wir deklarieren tinyInt arr[4];, die Adresse des zugewiesenen Speicherbereichs beginnt bei 1201. Sobald Sie arr[2] lesen müssen, müssen Sie die Adresse von arr[2] nur noch durch mathematische Berechnungen ermitteln. Um 1201 + (2 x 4) zu berechnen, beginnen Sie einfach direkt bei 1209 zu lesen.
Daten in JavaScript sind eine Hash-Map, die mithilfe verschiedener Datenstrukturen wie verknüpften Listen implementiert werden kann. Wenn Sie also in JavaScript ein Array var arr = new Array(4) deklarieren, generiert der Computer eine Struktur ähnlich der oben gezeigten. Wenn das Programm arr[2] lesen muss, muss es die Adressierung ab 1201 durchlaufen.
Die Unterschiede zwischen den oben genannten schnellen JavaScript-Arrays und echten Arrays. Offensichtlich sind mathematische Berechnungen schneller als das Durchlaufen einer verknüpften Liste. Dies gilt insbesondere für lange Arrays.
Die Entwicklung von JavaScript-Arrays
Ich frage mich, ob Sie sich an die Tage erinnern, als wir so neidisch auf den 256-MB-Computer waren, den unsere Freunde gekauft haben? Heutzutage sind überall 8 GB RAM vorhanden.
In ähnlicher Weise hat sich auch die JavaScript-Sprache stark weiterentwickelt. Von V8 und SpiderMonkey bis hin zu TC39 und der wachsenden Zahl von Webbenutzern haben enorme Anstrengungen JavaScript zu einer Notwendigkeit von Weltklasse gemacht. Sobald Sie über eine große Benutzerbasis verfügen, ist eine Leistungsverbesserung natürlich eine zwingende Voraussetzung.
Tatsächlich weisen moderne JavaScript-Engines zusammenhängenden Speicher für Arrays zu – wenn das Array homogen ist (alle Elemente sind vom gleichen Typ). Ein guter Programmierer stellt immer sicher, dass das Array homogen ist, damit der JIT (Just-in-Time-Compiler) die Elemente mithilfe von Berechnungen im C-Compiler-Stil lesen kann.
Sobald Sie jedoch ein Element eines anderen Typs in ein homogenes Array einfügen möchten, dekonstruiert die JIT das gesamte Array und erstellt es auf die alte Weise neu.
Wenn Ihr Code also nicht allzu schlecht ist, bleiben JavaScript-Array-Objekte hinter den Kulissen echte Arrays, was für moderne JS-Entwickler äußerst wichtig ist.
Darüber hinaus haben sich Arrays mit ES2015/ES6 weiter weiterentwickelt. TC39 hat beschlossen, typisierte Arrays (Typed Arrays) einzuführen, daher haben wir ArrayBuffer.
ArrayBuffer bietet einen kontinuierlichen Speicher, den wir nach Belieben bearbeiten können. Der direkte Betrieb des Speichers ist jedoch immer noch zu komplex und auf niedrigem Niveau. Es gibt also eine Ansicht, die ArrayBuffer verarbeitet. Es sind bereits einige Ansichten verfügbar, weitere werden in Zukunft hinzugefügt.
var buffer = new ArrayBuffer(8); var view = new Int32Array(buffer); view[0] = 100;
Hochleistungsfähige, effiziente typisierte Arrays wurden nach WebGL eingeführt. WebGL-Worker stehen vor einem großen Leistungsproblem, nämlich dem effizienten Umgang mit Binärdaten. Alternativ können Sie SharedArrayBuffer verwenden, um Daten zwischen mehreren Web Worker-Prozessen auszutauschen und so die Leistung zu verbessern.
Von einer einfachen Hash-Map zu einem SharedArrayBuffer zu wechseln, das ist ziemlich cool, oder?
Arrays im alten Stil vs. typisierte Arrays: Leistung
Wir haben die Entwicklung von JavaScript-Arrays bereits besprochen, jetzt testen wir, welchen Nutzen moderne Arrays uns bringen können. Hier sind einige Mikrotestergebnisse, die ich auf einem Mac mit Node.js 8.4.0 ausgeführt habe.
Array im alten Stil: Einfügen
var LIMIT = 10000000; var arr = new Array(LIMIT); console.time("Array insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.timeEnd("Array insertion time");
Zeit: 55 ms
Typed Array:插入 var LIMIT = 10000000; var buffer = new ArrayBuffer(LIMIT * 4); var arr = new Int32Array(buffer); console.time("ArrayBuffer insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.timeEnd("ArrayBuffer insertion time");
Zeit: 52 ms
Wrap, was sehe ich? Sind Arrays im alten Stil und ArrayBuffer gleichermaßen leistungsfähig? Nein, nein, nein. Denken Sie daran, wie bereits erwähnt, dass moderne Compiler intelligent genug sind, um herkömmliche Arrays desselben Elementtyps intern in speicherzusammenhängende Arrays umzuwandeln. Genau das ist beim ersten Beispiel der Fall. Trotz der Verwendung von new Array (LIMIT) existiert das Array immer noch als modernes Array.
Modifizieren Sie dann das erste Beispiel und ändern Sie das Array in ein heterogenes (Elementtypen sind nicht vollständig konsistent), um zu sehen, ob es einen Leistungsunterschied gibt.
旧式数组:插入(异构) var LIMIT = 10000000; var arr = new Array(LIMIT); arr.push({a: 22}); console.time("Array insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.timeEnd("Array insertion time");
Benötigte Zeit: 1207 ms
Die Änderung erfolgt in Zeile 3, indem eine Anweisung hinzugefügt wird, um das Array in einen heterogenen Typ zu ändern. Der Rest des Codes bleibt gleich. Der Leistungsunterschied zeigt sich, 22-mal langsamer.
Array im alten Stil: Lesen
var LIMIT = 10000000; var arr = new Array(LIMIT); arr.push({a: 22}); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } var p; console.time("Array read time"); for (var i = 0; i < LIMIT; i++) { //arr[i] = i; p = arr[i]; } console.timeEnd("Array read time");
Zeit: 196 ms
Typed Array:读取 var LIMIT = 10000000; var buffer = new ArrayBuffer(LIMIT * 4); var arr = new Int32Array(buffer); console.time("ArrayBuffer insertion time"); for (var i = 0; i < LIMIT; i++) { arr[i] = i; } console.time("ArrayBuffer read time"); for (var i = 0; i < LIMIT; i++) { var p = arr[i]; } console.timeEnd("ArrayBuffer read time");
Zeit: 27 ms
Fazit
Die Einführung typisierter Arrays ist ein großer Schritt in der Entwicklung von JavaScript. Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, dies sind typisierte Array-Ansichten, die native Endianness verwenden (wie native). Mit DataView können wir auch benutzerdefinierte Ansichtsfenster erstellen. Hoffentlich wird es in Zukunft weitere DataView-Bibliotheken geben, die uns dabei helfen, ArrayBuffers einfach zu manipulieren.
Die Entwicklung von JavaScript-Arrays ist sehr schön. Jetzt sind sie schnell, effizient, robust und intelligent genug bei der Speicherzuweisung.
Das obige ist der detaillierte Inhalt vonBeispiele für die Entwicklung und Leistungsanalyse von JavaScript-Arrays. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!