03 | 快属性和慢属性:V8是怎样提升对象属性访问速度的?
李兵
该思维导图由 AI 生成,仅供参考
你好,我是李兵。
在前面的课程中,我们介绍了 JavaScript 中的对象是由一组组属性和值的集合,从 JavaScript 语言的角度来看,JavaScript 对象像一个字典,字符串作为键名,任意对象可以作为键值,可以通过键名读写键值。
然而在 V8 实现对象存储时,并没有完全采用字典的存储方式,这主要是出于性能的考量。因为字典是非线性的数据结构,查询效率会低于线性的数据结构,V8 为了提升存储和查找效率,采用了一套复杂的存储策略。
线性结构和非线性结构
今天这节课我们就来分析下 V8 采用了哪些策略提升了对象属性的访问速度。
常规属性 (properties) 和排序属性 (element)
在开始之前,我们先来了解什么是对象中的常规属性和排序属性,你可以先参考下面这样一段代码:
在上面这段代码中,我们利用构造函数 Foo 创建了一个 bar 对象,在构造函数中,我们给 bar 对象设置了很多属性,包括了数字属性和字符串属性,然后我们枚举出来了 bar 对象中所有的属性,并将其一一打印出来,下面就是执行这段代码所打印出来的结果:
观察这段打印出来的数据,我们发现打印出来的属性顺序并不是我们设置的顺序,我们设置属性的时候是乱序设置的,比如开始先设置 100,然后又设置了 1,但是输出的内容却非常规律,总的来说体现在以下两点:
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
V8引擎通过采用快属性和慢属性的存储策略,提升了对象属性的访问速度。文章首先介绍了常规属性和排序属性的概念,以及它们在V8中的存储方式。通过将常规属性保存在对象本身,V8实现了快速属性访问,但当属性过多时会采用慢属性策略。此外,文章还介绍了对象内属性、内存布局和其他隐藏属性。通过Chrome开发者工具的内存快照,读者可以直观了解对象在内存中的布局。整体而言,本文深入浅出地解释了V8引擎如何提升对象属性访问速度的技术细节,对于想深入了解JavaScript引擎内部工作原理的读者具有很高的参考价值。 V8引擎通过快属性和慢属性的存储策略提升了对象属性的访问速度。文章介绍了常规属性和排序属性的概念,以及它们在V8中的存储方式。通过将常规属性保存在对象本身,V8实现了快速属性访问,但当属性过多时会采用慢属性策略。此外,文章还介绍了对象内属性、内存布局和其他隐藏属性。通过Chrome开发者工具的内存快照,读者可以直观了解对象在内存中的布局。整体而言,本文深入浅出地解释了V8引擎如何提升对象属性访问速度的技术细节,对于想深入了解JavaScript引擎内部工作原理的读者具有很高的参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》,新⼈⾸单¥59
《图解 Google V8》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(67)
- 最新
- 精选
- 伏枫https://www.cnblogs.com/chargeworld/p/12236848.html 找到了一篇博客,应该能帮助一些同学解惑
作者回复: 很赞
2020-03-23249 - try-catch执行完例子后有些疑惑,找到了v8引擎原博客 https://v8.dev/blog/fast-properties 中找到了答案: "The number of in-object properties is predetermined by the initial size of the object" in-object properties size 取决于初始化对象的大小。
作者回复: 赞,v8.dev里面的文章都不错
2020-03-2416 - HoSalt词典和字典是怎样的数据结构,类似于树?
作者回复: 就是hash表
2020-04-2421 - Lorin老师,hash表和js中对象是什么关系?我感觉对象就是哈希表,但是我看哈希表的定义里面key会经过哈希函数进行编码,这之间有什么区别呢?
作者回复: 你可以把对象看成是一个hash表,但是V8为了性能,做了很多改进
2020-03-251 - Longerian我在chrome里执行查看内存对象布局,搜索 Foo ,过滤出来的是空列表,这是为啥
作者回复: 在控制台执行了吗?
2020-03-236 - neohope1、chrome显示 不要关心一级目录上是否存在某个element或property,为了调试方便,chrome应该是无论如何存储,都会输出来。 直接去看elements和properties内存储的内容,更准确一些。 2、截图里property10怎么有两个: 这个问题,建议最好改一下演示代码,将Key和Value区分开,现在两个一样,容易引起一些误解。 3、element element没有内置。 element默认应该采用连续的存储结构,通过浪费空间换取时间,直接下标访问,提升访问速度。 但当element的序号十分不连续时,会优化成为hash表,因为要浪费的空间太大了,不合算。 4、property property有内置,只有十个,但建议把这十个单独考虑,后面就容易考虑清楚了。 property默认采用链表结构,当数据量很小时,查找也会很快,但数据量上升到某个数值后,会优化成为hash表。 因为超过某个数值,顺序查找就不够快了,需要通过hash表结构查找,提升速度。 5、hash表不是应该查找一次吗?为何是慢查询 hash表要解决key冲突问题,一般会用list存储多个冲突的key,所以计算hash后,还是要做顺序访问,所以要多次访问。 此外,还涉及到hash扩容的问题,那就更慢了。 所以,整体上来说,hash慢于按地址访问的; 在数据量小的时候,也慢于链表的顺序访问。 6、hash表如何存储property顺序? 再用一个链表记录插入属性就好了,类似于Java中的 LinkedHashMap ,就可以解决问题2020-07-2167
- cc有个疑问,properties在元素较少的时候使用链表存储的吗?在元素较多的时候换成查找树? properties存的属性key是字符串,应该不可能是数组存。要不就是链表,要不就是hash表。如果是hash表,那就没有必要切换成查找树,性能改变微乎其微,最多也就是把hash表里由于冲突导致的过长链表换成查找树。 对文章里所说的非线性结构和线性结构感到很困惑,比如链表和数组的查找性能就有很大区别,但又都是线性结构。所以为啥不直接说具体是数组还是链表? 字典的实现可以是哈希表或者查找树,哈希表是线性结构,查找树是非线性结构。 这节看下来这真是一头雾水。2020-03-221022
- 潇潇雨歇使用delete删除属性: 如果删除属性在线性结构中,删除后需要移动元素,开销较大,而且可能需要将慢属性重排到快属性。 如果删除属性在properties对象中,查找开销较大。2020-03-22518
- Silence老师,我的 Chrome 版本是 80 的,看 memory 面板好像和你讲的不太一样。 当有 20 个常规属性时,properties 中有 10 个,但是20 个都在 bar 对象内。 当有 100 个常规属性时,properties 就更诡异了,每个都有 2 个,共 200 个,bar 对象上有 100 个。 而且每次都是刷新浏览器后试的,这是什么情况? 评论区没办法截图。2020-03-211011
- 王楚然有几个问题没有弄懂: 1. element(排序属性)是否也有内置,快属性,慢属性三种?不会是一直线性存储吧? 2. 在properties(字符串属性)很多的时候,会大部分存储成字典结构,具体是什么样的字典结构呢?如何按照ECMA标准保证属性依据创建顺序排序呢? 3. 还有针对原文“线性的存储模式降级为非线性的字典存储模式,这样虽然降低了查找速度,但是却提升了修改对象的属性的速度。”这句话,线性存储模式是链表吗?字典存储是什么呢?修改的流程,应该也是先查找后修改吧?为什么后者会降低查找速度却能提高修改速度呢?2020-03-238
收起评论