Bevor wir beginnen, müssen wir darauf hinweisen, dass dieser Artikel nicht dazu gedacht ist, die Grundlagen von JavaScript-Arrays zu erklären, noch Syntax und Anwendungsfälle abzudecken. In diesem Artikel geht es mehr um Speicher, Optimierung, Syntaxunterschiede, Leistung und aktuelle Entwicklungen. 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 die jüngste Entwicklung. Freunde in Not können darauf verweisen, ich hoffe, es kann allen helfen.
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.
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");
Zeitaufwand: 1207 ms
改变发生在第 3 行,添加一条语句,将数组变为异构类型。其余代码保持不变。性能差异表现出来了,慢了 22 倍。
旧式数组:读取
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");
用时:196ms
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");
用时:27ms
结论
类型化数组的引入是 JavaScript 发展历程中的一大步。Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,这些是类型化数组视图,使用原生字节序(与本机相同)。我们还可以使用 DataView 创建自定义视图窗口。希望未来会有更多帮助我们轻松操作 ArrayBuffer 的 DataView 库。
JavaScript 数组的演进非常 nice。现在它们速度快、效率高、健壮,在内存分配时也足够智能。
相关推荐:
Das obige ist der detaillierte Inhalt vonEntwicklung und Leistungsanalyse von JavaScript-Arrays. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!