Maison > Article > interface Web > Évolution des tableaux JavaScript et analyse des performances
Avant de commencer, nous devons préciser que cet article n'a pas pour but d'expliquer les bases des tableaux JavaScript, ni de couvrir la syntaxe et les cas d'utilisation. Cet article parle davantage de la mémoire, de l'optimisation, des différences de syntaxe, des performances et des évolutions récentes. Cet article présente principalement l'évolution et l'analyse des performances des tableaux JavaScript. Cet article parle davantage de la mémoire, de l'optimisation, des différences de syntaxe, des performances et de l'évolution récente. Les amis dans le besoin peuvent s'y référer, j'espère que cela pourra aider tout le monde.
Avant d'utiliser JavaScript, j'étais déjà assez familier avec C, C++ et C#. Comme beaucoup de développeurs C/C++, ma première impression de JavaScript n’a pas été bonne.
Array est l'une des principales raisons. Les tableaux JavaScript ne sont pas contigus et sont implémentés comme des cartes de hachage ou des dictionnaires. J'ai l'impression que c'est un peu un langage de niveau B et que l'implémentation du tableau est tout simplement inappropriée. Depuis lors, JavaScript et ma compréhension de celui-ci ont beaucoup changé.
Pourquoi les tableaux JavaScript ne sont pas de vrais tableaux
Avant de parler de JavaScript, parlons d'abord de ce qu'est un tableau.
Un tableau est une séquence contiguë d'emplacements mémoire utilisés pour contenir une certaine valeur. Il est important de noter l'accent mis sur « continu » (ou contigu).
La figure ci-dessus montre comment les tableaux sont stockés en mémoire. Ce tableau contient 4 éléments, chaque élément fait 4 octets. Au total, il occupe 16 octets de zone mémoire.
Supposons que nous déclarions tinyInt arr[4];, l'adresse de la zone mémoire allouée commence à 1201. Une fois que vous avez besoin de lire arr[2], il vous suffit d'obtenir l'adresse de arr[2] via des calculs mathématiques. Pour calculer 1201 + (2 X 4), commencez simplement à lire directement à partir de 1209.
Les données en JavaScript sont une carte de hachage, qui peut être implémentée en utilisant différentes structures de données, telles que des listes chaînées. Ainsi, si vous déclarez un tableau en JavaScript var arr = new Array(4), l'ordinateur générera une structure similaire à celle présentée ci-dessus. Si le programme a besoin de lire arr[2], il doit parcourir l'adressage à partir de 1201.
Les différences entre les tableaux JavaScript rapides ci-dessus et les tableaux réels. De toute évidence, les calculs mathématiques sont plus rapides que le parcours d'une liste chaînée. Cela est particulièrement vrai pour les tableaux longs.
L'évolution des tableaux JavaScript
Je me demande si vous vous souvenez de l'époque où nous enviions tant l'ordinateur de 256 Mo que nos amis achetaient ? Aujourd'hui, 8 Go de RAM sont partout.
De même, le langage JavaScript a également beaucoup évolué. De V8 et SpiderMonkey à TC39 et au nombre croissant d'utilisateurs Web, d'énormes efforts ont fait de JavaScript une nécessité de classe mondiale. Une fois que vous disposez d’une énorme base d’utilisateurs, l’amélioration des performances est naturellement une exigence essentielle.
En fait, les moteurs JavaScript modernes alloueront de la mémoire contiguë aux tableaux - si le tableau est homogène (tous les éléments sont du même type). Un bon programmeur veillera toujours à ce que le tableau soit homogène afin que le JIT (compilateur juste à temps) puisse lire les éléments à l'aide de calculs de style compilateur C.
Cependant, une fois que vous souhaitez insérer un élément d'un autre type dans un tableau homogène, le JIT déconstruira l'intégralité du tableau et le recréera à l'ancienne.
Donc, si votre code n'est pas trop mauvais, les objets JavaScript Array restent de véritables tableaux en coulisses, ce qui est extrêmement important pour les développeurs JS modernes.
De plus, les baies ont davantage évolué après ES2015/ES6. TC39 a décidé d'introduire des tableaux typés (Typed Arrays), nous avons donc ArrayBuffer.
ArrayBuffer fournit une mémoire continue que nous pouvons opérer à volonté. Cependant, exploiter directement la mémoire est encore trop compliqué et de faible niveau. Il existe donc une vue qui gère ArrayBuffer. Quelques vues sont déjà disponibles et d'autres seront ajoutées à l'avenir.
var buffer = new ArrayBuffer(8); var view = new Int32Array(buffer); view[0] = 100;
Des tableaux typés performants et efficaces ont été introduits après WebGL. Les travailleurs WebGL rencontrent un énorme problème de performances, à savoir comment gérer efficacement les données binaires. Vous pouvez également utiliser SharedArrayBuffer pour partager des données entre plusieurs processus Web Worker afin d'améliorer les performances.
Passer d'une simple hash map à maintenant un SharedArrayBuffer, c'est plutôt cool, non ?
Tableaux à l'ancienne vs tableaux typés : performances
Nous avons déjà discuté de l'évolution des tableaux JavaScript, testons maintenant les avantages que les tableaux modernes peuvent nous apporter. Voici quelques résultats de micro-tests que j'ai exécutés sur un Mac en utilisant Node.js 8.4.0.
Tableau à l'ancienne : insérer
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");
temps : 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");
temps : 52 ms
Enrouler, qu'est-ce que je vois ? Les tableaux à l'ancienne et ArrayBuffer sont-ils également performants ? Non non non. N'oubliez pas que, comme mentionné précédemment, les compilateurs modernes sont suffisamment intelligents pour convertir en interne des tableaux traditionnels du même type d'élément en tableaux contigus en mémoire. C'est exactement le cas du premier exemple. Malgré l'utilisation du nouveau tableau (LIMIT), le tableau existe toujours en tant que tableau moderne.
Modifiez ensuite le premier exemple et changez le tableau en un tableau hétérogène (les types d'éléments ne sont pas complètement cohérents) pour voir s'il y a une différence de performances.
旧式数组:插入(异构) 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");
Durée prise : 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。现在它们速度快、效率高、健壮,在内存分配时也足够智能。
相关推荐:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!