js性能优化之数组模式

首先我们来看看下面这两段代码,两段代码都是在初始化一个长度为1亿的数组,唯一区别是在片段二中,先为最后一项赋值1次,大家觉得会有区别吗?

代码一:

js 复制代码
const arr1 = [];
for ( let i = 0; i < 100000000; ++i ) {
  arr1[i] = 1;
}

代码二:

js 复制代码
const arr2 = [];
arr2[100000000 - 1] = 1;
for ( let i = 0; i < 100000000; ++i ) {
  arr2[i] = 1;
}

我们来尝试执行一下:

可以看到片段二比片段一要耗时多出许多,片段一的耗时是318毫秒,片段二的耗时是1343毫秒,中间仅仅因为片段二先为最后一项赋值了1次。

片段二之所以会多出这部分的耗时,归根结底是因为v8会以不同的形式去存储js的数组。

第一种模式是快速模式,V8对应用c语言的数组来对js的数组进行存储,具备速度快,紧凑的特点。

第二种模式是字典模式,v8 对应用c语言的哈希表来对js的数组进行存储,特点是速度慢松散。

两种模式的触发机制如下:

如果数组从首位到最后一位是紧凑的,中间无空洞;或者预分配给数组的大小,小于10万,无论中间有没有空洞,都会进入快速模式。

但是如果预分配给数组的大小,大于等于10万,且中间有空洞,这样就会把数组进入字典模式。

我们再回到最开始的例子:

例子的逻辑是,首先我们定义一个数组,再为数组的最后一位赋1,在这个时候,这个数组已经具备了一定的长度,而且这个长度是大于10万的,而且这个数组中间是有非常多的空洞,只有最后一位有数字。这就意味着在这段片段里面执行完之后,数组就会在v8里面去进入了字典模式,而字典模式的特点是松散,而且执行相对比较慢,就会导致前面的一段时间耗时会多出许多,这就是底层的原因。

优化策略:

  1. 从0开始连续的初始化数组,以避免数组进入字典模式。
  2. 不要预分配一个超大数组 (比如长度大于等于 100000)
  3. 删除数组元素时让数组保持紧凑,尽可能避免使用 delete。
  4. 不要访问未初始化或已删除的数组元素。
相关推荐
会跑的葫芦怪2 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
xiaoqi9223 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233223 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头88215 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas1365 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
2601_949833395 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter
军军君016 小时前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three
xiaoqi9227 小时前
React Native鸿蒙跨平台如何实现分类页面组件通过searchQuery状态变量管理搜索输入,实现了分类的实时过滤功能
javascript·react native·react.js·ecmascript·harmonyos
qq_177767378 小时前
React Native鸿蒙跨平台实现应用介绍页,实现了应用信息卡片展示、特色功能网格布局、权限/联系信息陈列、评分展示、模态框详情交互等通用场景
javascript·react native·react.js·ecmascript·交互·harmonyos
2603_949462108 小时前
Flutter for OpenHarmony社团管理App实战:预算管理实现
android·javascript·flutter