提升 javascript 代码性能

今天我们通过分析在 V8 引擎中是如何提升我们代码的性能的。今天先谈常见的元素种类

8207483-2174e1f89f8f2db8.jpg

运行 JavaScript 代码时,V8 会跟踪每个数组所包含的元素。这些信息可以帮助 V8 优化数组元素的操作。例如,当您在数组上调用 reduce,map 或 forEach 时,V8 可以根据数组包含哪些元素来优化这些操作。

在 JavaScript 代码中,创建一个由数字类型的值组成的数组,当您在数组上调用 reduce,map 或 forEach 时,V8 可以根据数组包含哪些元素来优化这些操作。


在 JavaScript 我们可以为数组添加任意的数据类型的元素。就这个数组来说,如果你使用 typeof 操作符检查每个元素的类型,javascript 会告诉你数组包含都是 numbers。在语言层面,JavaScript 不区分整数,浮点数和双精度 - 只是数字。然而,在引擎级别,可以做出更精确的区分。


8207483-3228e3d456e650ae.jpg

这个数组的元素是 PACKED_SMI_ELEMENTS。在 V8中,术语 Smi 是指用于存储小整数的特定格式。(后面我们会在 PACKED 部分中说明。)

8207483-8c1df9e64bb3d545.jpg

如果我们添加 4.56 到数组。

8207483-7b66644395e9c565.jpg

这时我们的元素的类型就需要升级为 PACKED DOUBLE ELEMENTS 请注意,双精度浮点数是 Smi 的更为一般的变体,而常规元素是双精度浮点数之上的另一个概括。可以表示为 Smi 的数字集合是可以表示为 double 的数字的子集。

8207483-7d8c30a40128b2cb.jpg

我们继续向数组添加新的元素,这次是字符串 x 。元素类型也升级到 PACKED ELEMENT

8207483-60c20cc2ab9e537d.jpg

值得注意的是,元素种类转换只能从一个方向进行:从特定的(如 PACKED_SMI_ELEMENTS)到更一般的(例如 PACKED_ELEMENTS)。例如,一旦数组被标记为 PACKED_ELEMENTS,元素就不能回到 PACKED_DOUBLE_ELEMENTS。

8207483-9f3b257217f89d57.jpg

我们表格形式表示上面我们创建的长度为 5 的数组。

8207483-d0d60af9b4c73fad.jpg

如果我们现在跳过一些位置,对数组索引为 9 位置为 10 的进行赋值,那么就在 5 - 8 位置上留下空位。

8207483-a785f500e98ccd26.jpg

因为这些空位存在我们的元素类型就变为了 HOLEY_ELEMENTS。

8207483-4e286464583bf236.jpg

在计算过程中可能我们需要获取索引为 8 位子上的数值。

8207483-d1b1bc310ec809ed.jpg

1. 首先检查数组的索引是否大于 0 并且确保该索引没有溢出。

8207483-b934597a17200442.jpg

2. 调用该 array 的 hasOwnProperty 来检查是否存储值为 8 的属性值。

8207483-1217a7492252c68b.jpg

3. 如果在该 array 上无法找到属性为 8 的值,我们都知道 javascript 是靠原型链来实现继承的,所以会继续向上查找 Array.property 是否具有该属性。

8207483-611fe1f3de055ac4.jpg

我们继续向上追溯,因为 Array是源于也就是继承于 Object 所以检查 Object.prototype 是否与8 的属性。

8207483-aa6ff7c19d465e24.jpg
8207483-9721ec8b6193bf7f.jpg

最后我们顺着原型链向上查找,发现没有属性 8 对应的值,得出结论在 80 位置上没有值 undefined。对于有空位置这样稀疏数值,检验是否存在的成本是高价的。我们再看检查密集(packedArray) 这样没有空位置数据是我们无需过多的步骤就可以判断是否存在值。

8207483-4cf5f4ef8a7ed814.jpg


8207483-16e47b81d9e51821.jpg

所以我们在开发时要避免有空位置的稀疏数组,取而代之尽量使用没有空位置的密集数组。

8207483-e48d5e9b6e08ef93.jpg

猜你喜欢

转载自blog.csdn.net/weixin_34106122/article/details/86797421