图解 Google V8
李兵
前盛大创新院高级研究员
26763 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 25 讲
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

03 | 快属性和慢属性:V8是怎样提升对象属性访问速度的?

存储策略权衡
对象内属性(in-object properties)
V8内部存储结构
ECMAScript规范定义
不建议使用delete的原因
内置内属性策略
提升查找效率
V8对象存储方式
proto属性
map属性
对象内存布局
内存快照
快属性和慢属性
常规属性(properties)和排序属性(element)
思考题
总结
其他属性
实践:在Chrome中查看对象布局
V8对象存储策略
V8对象属性访问速度优化

该思维导图由 AI 生成,仅供参考

你好,我是李兵。
在前面的课程中,我们介绍了 JavaScript 中的对象是由一组组属性和值的集合,从 JavaScript 语言的角度来看,JavaScript 对象像一个字典,字符串作为键名,任意对象可以作为键值,可以通过键名读写键值。
然而在 V8 实现对象存储时,并没有完全采用字典的存储方式,这主要是出于性能的考量。因为字典是非线性的数据结构,查询效率会低于线性的数据结构,V8 为了提升存储和查找效率,采用了一套复杂的存储策略。
线性结构和非线性结构
今天这节课我们就来分析下 V8 采用了哪些策略提升了对象属性的访问速度。

常规属性 (properties) 和排序属性 (element)

在开始之前,我们先来了解什么是对象中的常规属性排序属性,你可以先参考下面这样一段代码:
function Foo() {
this[100] = 'test-100'
this[1] = 'test-1'
this["B"] = 'bar-B'
this[50] = 'test-50'
this[9] = 'test-9'
this[8] = 'test-8'
this[3] = 'test-3'
this[5] = 'test-5'
this["A"] = 'bar-A'
this["C"] = 'bar-C'
}
var bar = new Foo()
for(key in bar){
console.log(`index:${key} value:${bar[key]}`)
}
在上面这段代码中,我们利用构造函数 Foo 创建了一个 bar 对象,在构造函数中,我们给 bar 对象设置了很多属性,包括了数字属性和字符串属性,然后我们枚举出来了 bar 对象中所有的属性,并将其一一打印出来,下面就是执行这段代码所打印出来的结果:
index:1 value:test-1
index:3 value:test-3
index:5 value:test-5
index:8 value:test-8
index:9 value:test-9
index:50 value:test-50
index:100 value:test-100
index:B value:bar-B
index:A value:bar-A
index:C value:bar-C
观察这段打印出来的数据,我们发现打印出来的属性顺序并不是我们设置的顺序,我们设置属性的时候是乱序设置的,比如开始先设置 100,然后又设置了 1,但是输出的内容却非常规律,总的来说体现在以下两点:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

V8引擎通过采用快属性和慢属性的存储策略,提升了对象属性的访问速度。文章首先介绍了常规属性和排序属性的概念,以及它们在V8中的存储方式。通过将常规属性保存在对象本身,V8实现了快速属性访问,但当属性过多时会采用慢属性策略。此外,文章还介绍了对象内属性、内存布局和其他隐藏属性。通过Chrome开发者工具的内存快照,读者可以直观了解对象在内存中的布局。整体而言,本文深入浅出地解释了V8引擎如何提升对象属性访问速度的技术细节,对于想深入了解JavaScript引擎内部工作原理的读者具有很高的参考价值。 V8引擎通过快属性和慢属性的存储策略提升了对象属性的访问速度。文章介绍了常规属性和排序属性的概念,以及它们在V8中的存储方式。通过将常规属性保存在对象本身,V8实现了快速属性访问,但当属性过多时会采用慢属性策略。此外,文章还介绍了对象内属性、内存布局和其他隐藏属性。通过Chrome开发者工具的内存快照,读者可以直观了解对象在内存中的布局。整体而言,本文深入浅出地解释了V8引擎如何提升对象属性访问速度的技术细节,对于想深入了解JavaScript引擎内部工作原理的读者具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《图解 Google V8》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(67)

  • 最新
  • 精选
  • 伏枫
    https://www.cnblogs.com/chargeworld/p/12236848.html 找到了一篇博客,应该能帮助一些同学解惑

    作者回复: 很赞

    2020-03-23
    2
    49
  • 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-24
    16
  • HoSalt
    词典和字典是怎样的数据结构,类似于树?

    作者回复: 就是hash表

    2020-04-24
    2
    1
  • Lorin
    老师,hash表和js中对象是什么关系?我感觉对象就是哈希表,但是我看哈希表的定义里面key会经过哈希函数进行编码,这之间有什么区别呢?

    作者回复: 你可以把对象看成是一个hash表,但是V8为了性能,做了很多改进

    2020-03-25
    1
  • Longerian
    我在chrome里执行查看内存对象布局,搜索 Foo ,过滤出来的是空列表,这是为啥

    作者回复: 在控制台执行了吗?

    2020-03-23
    6
  • neohope
    1、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-21
    67
  • cc
    有个疑问,properties在元素较少的时候使用链表存储的吗?在元素较多的时候换成查找树? properties存的属性key是字符串,应该不可能是数组存。要不就是链表,要不就是hash表。如果是hash表,那就没有必要切换成查找树,性能改变微乎其微,最多也就是把hash表里由于冲突导致的过长链表换成查找树。 对文章里所说的非线性结构和线性结构感到很困惑,比如链表和数组的查找性能就有很大区别,但又都是线性结构。所以为啥不直接说具体是数组还是链表? 字典的实现可以是哈希表或者查找树,哈希表是线性结构,查找树是非线性结构。 这节看下来这真是一头雾水。
    2020-03-22
    10
    22
  • 潇潇雨歇
    使用delete删除属性: 如果删除属性在线性结构中,删除后需要移动元素,开销较大,而且可能需要将慢属性重排到快属性。 如果删除属性在properties对象中,查找开销较大。
    2020-03-22
    5
    18
  • Silence
    老师,我的 Chrome 版本是 80 的,看 memory 面板好像和你讲的不太一样。 当有 20 个常规属性时,properties 中有 10 个,但是20 个都在 bar 对象内。 当有 100 个常规属性时,properties 就更诡异了,每个都有 2 个,共 200 个,bar 对象上有 100 个。 而且每次都是刷新浏览器后试的,这是什么情况? 评论区没办法截图。
    2020-03-21
    10
    11
  • 王楚然
    有几个问题没有弄懂: 1. element(排序属性)是否也有内置,快属性,慢属性三种?不会是一直线性存储吧? 2. 在properties(字符串属性)很多的时候,会大部分存储成字典结构,具体是什么样的字典结构呢?如何按照ECMA标准保证属性依据创建顺序排序呢? 3. 还有针对原文“线性的存储模式降级为非线性的字典存储模式,这样虽然降低了查找速度,但是却提升了修改对象的属性的速度。”这句话,线性存储模式是链表吗?字典存储是什么呢?修改的流程,应该也是先查找后修改吧?为什么后者会降低查找速度却能提高修改速度呢?
    2020-03-23
    8
收起评论
显示
设置
留言
67
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部