一文带你弄懂 V8 数组的快速 / 字典模式

V8 是如何处理数组的?

问题

先抛出一个问题,下面两端代码哪个的效率更高?

const arr = [];
for(let i = 0; i < 10000000; i++) {
  arr[i] = 1;
}
const arr = [];
arr[10000000 - 1] = 1;
for(let i = 0; i < 10000000; i++) {
  arr[i] = 1;
}

答案是第一段代码的效率更高,先来看执行的耗时,运行下面的代码:

console.time('a')
const arr1 = [];
for (let i = 0; i < 10000000; i++) {
  arr1[i] = 1;
}
console.timeEnd('a')

console.time('b')
const arr = [];
arr[10000000 - 1] = 1;
for (let i = 0; i < 10000000; i++) {
  arr[i] = 1;
}
console.timeEnd('b')

控制台的输出如下:

在这里插入图片描述

可以很明显的看到执行耗时的差别,第一段代码的效率远高于第二段代码。

那么,这是为什么呢?

原因

其实是 V8 底层对数组有两种处理方式,一种是 “快速模式”(Fast Elements),另一种是 “字典模式”(Dictionary Elements),那么这两种模式分别会在什么情况下触发,以及都有什么区别呢?

快速模式

特点:快速模式是针对紧凑型数组(dense array)的优化,这种数组的特点是索引是连续的,没有“空洞”(即没有未定义的索引)。

内部处理:在快速模式下,V8 使用类似于 C++ 数组的结构来存储元素。这意味着它为数组元素分配了连续的内存空间,提高了元素访问的速度。

适用情况:当你创建的数组是紧凑的,且主要进行的是对数组元素的遍历和访问操作时,V8 会使用这种模式。

字典模式

特点:当数组变得稀疏(sparse),即数组中有大量的空洞,或者数组索引非常大时,V8 会将数组转换为字典模式。

内部处理:在字典模式下,数组被处理为一个哈希表,而不是连续的内存块。这种方式在处理大量空洞或非常大的索引时更加内存高效。

适用情况:对于具有非常高索引值或大量未定义元素的数组,或者频繁更改其大小的数组,V8 会采用这种模式。

区别

  1. 底层的数据结构
    • 快速模式采用的是 Array
    • 字典模式采用的是 HashMap
  2. 触发方式
    • 默认是快速模式
    • 当存在以下情况就会转换到字典模式
      1. 数组存在 “空洞”,变为稀疏数组
      2. 数组中的值存在多种数据类型也可能转换,例如:同时存储数字、字符串、对象等
      3. 数组的长度接近或超过 32 位整数的最大值
  3. 效率
    • 快速模式的访问和遍历效率更高
    • 字典模式处理稀疏数组的效率更高

应用场景

尽量使用快速模式,可以通过以下方式来处理长度过长的数组:

  1. 数组分片:将一个数组分为多个数组,在处理时分别处理各个子数组
  2. 采用 Map 或 Set 替换数组:在某些情况下 Map 或 Set 可能比稀疏数组更加高效

PS:绝大多数情况下都不太需要关注,除非这对性能的造成了很明显的影响或需要对性能进行重度优化的情况下,因为 V8 本身已经提供了很优秀的性能。

参考:https://itnext.io/v8-deep-dives-understanding-array-internals-5b17d7a28ecc

PS

作者整理了一份长达 9w+ 字数,字节、阿里、百度大佬看了都称赞的前端文档,并且还在持续更新,包含:

  1. HTML、CSS、JavaScript 三件套
  2. Vue、React 流行框架
  3. Webpack、Vite 构建工具
  4. 浏览器、安全、计算机网络、操作系统、设计模式等计算机领域基本功
  5. etc…

在这里插入图片描述

可以添加作者 Q: 1437517225 备注领取,文档可以参与评论,以及给作者留言想要的问题,欢迎大家参与共建。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/300427.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一文搞定通过UTM 在MAC M1上安装Win11

Why 临近过年&#xff0c;一年一度的抢票大战就要开始。抢票软件要求安装在windows&#xff0c;作为mac资深用户&#xff0c;必须安装个windows虚拟机。 How step by step: follow YouTube。具体step follow YouTube 视频。本文&#xff0c;只说一下&#xff0c;特别容易错…

Unity中Shader面片一直面向摄像机(个性化修改及适配BRP)

文章目录 前言一、个性化修改面向摄像机效果1、把上一篇文章中求的 Z轴基向量 投影到 XoZ平面上2、其余步骤和之前的一致3、在属性面板定义一个变量&#xff0c;控制面片面向摄像机的类型4、效果 二、适配BRP三、最终代码 前言 在上一篇文章中&#xff0c;我们用Shader实现了面…

1.7 day5 IO进程线程

互斥锁 #include <myhead.h> char buf[128];//创建临界资源 pthread_mutex_t mutex;//创建锁 void *task(void *arg)//分支线程 {while(1){pthread_mutex_lock(&mutex);//上锁printf("分支线程:buf%s\n",buf);strcpy(buf,"I Love China");pthre…

mysql基础-表数据操作之查

目录 1.别名 2. 单表查询 2.1 模糊查询 - like 2.2 limit 2.3 order by 2.4 group by 2.5 in 2.6 between and 2.6 is null 2.7 not 2.8 运算符 3. 联表查询 全连接 左连接 右连接 本次分享一下数据的DQL语言。 1.别名 首先分享一下别名的知识。我们在查询的时…

【创建VirtualBox虚拟机并安装openEuler20.03 TLS SP1操作系统】

创建VirtualBox虚拟机并安装openEuler20.03 TLS SP1操作系统 一、环境说明二、安装过程 一、环境说明 虚拟机软件&#xff1a;Virtualbox操作系统&#xff1a;openEuler 20.03 TLS SP1&#xff08;x86&#xff09; 二、安装过程 创新虚拟机 修改虚拟机配置&#xff1a; …

MySQL复习汇总(图书管理系统)

MySQL图书管理系统&#xff08;49-94&#xff09;源码_71.备份book数据库到e盘的mybook.sql文件(备份文件中要求包含建库命令)-CSDN博客 -- 1、 创建一个名称为book的数据库。 -- 2、 打开book数据库 -- 3、 创建数据表分别如下&#xff08;除外键之外&#xff09;…

IDEA 中搭建 Spring Boot Maven 多模块项目 (父SpringBoot+子Maven)

第1步&#xff1a;新建一个SpringBoot 项目 作为 父工程 [Ref] 新建一个SpringBoot项目 删除无用的 .mvn 目录、 src 目录、 mvnw 及 mvnw.cmd 文件&#xff0c;最终只留 .gitignore 和 pom.xml 第2步&#xff1a;创建 子maven模块 第3步&#xff1a;整理 父 pom 文件 ① …

支付宝扫码(Easy版)支付实现

文章目录 一 技术准备1.1 二维码技术&#xff08;java&#xff09;1.2 支付宝沙箱环境准备1.3 内网穿透 二 支付宝支付相关知识2.1 各种支付方式2.2 扫码付接入流程2.3 系统交互流程(时序图)2.4 加密逻辑 三 扫码支付实现3.1 添加maven依赖&#xff08;Easy版&#xff09;3.2 完…

【Python发送邮件】

Python发送邮件 使用python的email和smtplib发送邮件 使用python的email和smtplib发送邮件 需要先下载安装 email 和 smtplib 模块 // An highlighted block pip install email smtplib需要去你的邮件地址申请一下 API Key&#xff0c;这是专门用来开发时使用的密钥。 获取后…

看CHAT如何判断php Imagick writeImages写入gif已经完毕

CHAT回复&#xff1a;Imagick::writeImages() 是同步执行的&#xff0c;也就是说这个函数会阻塞直到 GIF 文件被完全写出。所以如果这个函数没有报错并成功返回&#xff0c;那么你可以认为 GIF 文件已经被完全写出了。 如果你想要在写出 GIF 文件后立即做一些操作&#xff08;例…

学习c语言,隐形类型转换,整形提升

把整形定义字符型的话&#xff0c;字符型指挥提取整形前8位&#xff0c;但是整形有32位&#xff0c;如果字符型最后一位为0全部补0&#xff0c;为1全部补1。

测试分类篇

小王学习录 测试分类按测试对象划分1. 界面测试2. 可靠性测试3. 容错性测试4. 文档测试5. 兼容性测试6. 易用性测试7. 安装卸载测试8. 安全测试9. 性能测试10. 内存泄露测试 按是否查看代码划分1. 黑盒测试2. 白盒测试3. 灰盒测试 按开发阶段分1. 单元测试2. 集成测试3. 系统测…

WebofScience快速检索文献的办法

Web of Science为什么老是搜不到文章&#xff0c;原来是要在这个地方全部勾选 如果是搜标题的话&#xff0c;选Title&#xff0c;输入你要搜的文章标题 另外&#xff0c;也可以在浏览器直接搜文章标题&#xff0c;得到文章的DOI&#xff0c;然后选DOI&#xff0c;直接搜DOI也行…

draw.io基础操作和代码高效画图进阶

文章目录 一、基础操作1、链接2、等比例变形3、复制4、插入表格 二、在线打开三、插入—功能聚集地1、插入图片2、插入画笔3、插入布局4、导出 四、图码转换——高效画图1、通用图码转换2、流程图生成&#xff1a;使用mermaid语言生成图&#xff1a; 五、图码转换高效画图的典型…

超维空间M1无人机使用说明书——52、ROS无人机二维码识别与降落

引言&#xff1a;使用二维码引导无人机实现精准降落&#xff0c;首先需要实现对二维码的识别和定位&#xff0c;可以参考博客的二维码识别和定位内容。本小节主要是通过获取拿到的二维码位置&#xff0c;控制无人机全向的移动和降落&#xff0c;分为两种&#xff0c;一种是无人…

问题:为什么IP和端口一样的两个应用服务可以正常启动呢?

mysql安装 将MongoDB安装好并设置bindIP为0.0.0.0&#xff0c;端口为3306 发现问题&#xff0c;MySQL和MongoDB端口和IP一致&#xff0c;两个服务都能同时启动&#xff0c;这是为什么呢&#xff1f; 麻烦知道的大佬帮忙解答一下~~~

win10下安装detectron2-0.5(0.6应该也可以)

最近从github上下载的实例分割代码是detectron2-0.5的记录下配置过程。 1、前面什么pytorch基本步骤网上教程很多, 对着项目的要求下就行 2、到这里一般都是让你去下一个detectron2&#xff0c;但是我们从github上白嫖的项目都是有detectron2的&#xff0c;所以只需要找到那个s…

DQL命令查询数据(三)

本课目标 掌握MySQL的多表查询 SQL语句的综合应用 多表连接查询 通过各个表之间共同列的关联性&#xff08;例如&#xff1a;外键&#xff09;来查询的 分类&#xff1a; 内连接(INNER JOIN) &#xff0c;可简写为 JOIN&#xff1b;左外连接(LEFT OUTER JOIN)&#xff0c;…

【EAI 004】LLM+P:借助LLM和PDDL赋予机器人最优规划能力

论文标题&#xff1a;LLMP: Empowering Large Language Models with Optimal Planning Proficiency 论文作者&#xff1a;Bo Liu, Yuqian Jiang, Xiaohan Zhang, Qiang Liu, Shiqi Zhang, Joydeep Biswas, Peter Stone 作者单位&#xff1a;Department of Computer Science, Th…

【前端设计】小球loading动画

欢迎来到前端设计专栏&#xff0c;本专栏收藏了一些好看且实用的前端作品&#xff0c;使用简单的html、css语法打造创意有趣的作品&#xff0c;为网站加入更多高级创意的元素。 html <!DOCTYPE html> <html lang"en"> <head><meta charset&quo…