图解 Google V8
李兵
前盛大创新院高级研究员
立即订阅
2540 人已学习
课程目录
已更新 7 讲 / 共 24 讲
0/4登录后,你可以任选4讲全文学习。
宏观视角 (2讲)
开篇词 | 如何学习谷歌高性能 JavaScript 引擎V8?
免费
01 | V8是如何执行一段JavaScript代码的?
JavaScript设计思想篇 (5讲)
02 | 函数即对象:一篇文章彻底搞懂JavaScript的函数特点
03|快属性和慢属性:V8采用了哪些策略提升了对象属性的访问速度?
04 | 函数表达式:涉及大量概念,函数表达式到底该怎么学?
05|原型链: V8是如何实现对象继承的?
06|作用域链:V8是如何查找变量的?
图解 Google V8
登录|注册

03|快属性和慢属性:V8采用了哪些策略提升了对象属性的访问速度?

李兵 2020-03-21
你好,我是李兵。
在前面的课程中,我们介绍了 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/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《图解 Google V8》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(31)

  • 伏枫
    https://www.cnblogs.com/chargeworld/p/12236848.html
    找到了一篇博客,应该能帮助一些同学解惑
    2020-03-23
    6
  • Silence
    老师,我的 Chrome 版本是 80 的,看 memory 面板好像和你讲的不太一样。
    当有 20 个常规属性时,properties 中有 10 个,但是20 个都在 bar 对象内。
    当有 100 个常规属性时,properties 就更诡异了,每个都有 2 个,共 200 个,bar 对象上有 100 个。
    而且每次都是刷新浏览器后试的,这是什么情况?
    评论区没办法截图。
    2020-03-21
    4
    5
  • YAN
    有个疑问,properties在元素较少的时候使用链表存储的吗?在元素较多的时候换成查找树?
    properties存的属性key是字符串,应该不可能是数组存。要不就是链表,要不就是hash表。如果是hash表,那就没有必要切换成查找树,性能改变微乎其微,最多也就是把hash表里由于冲突导致的过长链表换成查找树。

    对文章里所说的非线性结构和线性结构感到很困惑,比如链表和数组的查找性能就有很大区别,但又都是线性结构。所以为啥不直接说具体是数组还是链表?
    字典的实现可以是哈希表或者查找树,哈希表是线性结构,查找树是非线性结构。

    这节看下来这真是一头雾水。


    2020-03-22
    1
    4
  • 马成
    老师,字典结构为什么读取效率比线性结构低。如果都是数字索引的话,线性结构很快,但是字符串属性只能遍历呀,怎么会比字典快呢?
    2020-03-21
    5
    3
  • 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
    1
  • 青史成灰
    老师,这里的线形、非线形数据结构,能否说的具体点,是数组,链表,红黑树还是啥的
    2020-03-24
    1
  • 王楚然
    有几个问题没有弄懂:
    1. element(排序属性)是否也有内置,快属性,慢属性三种?不会是一直线性存储吧?
    2. 在properties(字符串属性)很多的时候,会大部分存储成字典结构,具体是什么样的字典结构呢?如何按照ECMA标准保证属性依据创建顺序排序呢?
    3. 还有针对原文“线性的存储模式降级为非线性的字典存储模式,这样虽然降低了查找速度,但是却提升了修改对象的属性的速度。”这句话,线性存储模式是链表吗?字典存储是什么呢?修改的流程,应该也是先查找后修改吧?为什么后者会降低查找速度却能提高修改速度呢?
    2020-03-23
    1
  • 潇潇雨歇
    使用delete删除属性:
    如果删除属性在线性结构中,删除后需要移动元素,开销较大,而且可能需要将慢属性重排到快属性。
    如果删除属性在properties对象中,查找开销较大。
    2020-03-22
    1
  • 一步
    关于常规属性过多时候的表现我这里有2个问题想请教一下:
    1、我这里和老师实验结果不一样:我这里利用 Chrome 创建了 30个常规属性,我看了一下是没有使用对象内属性的,30 个属性以字典的形式保存的 properties 属性对象中
    2、当转化为字典后,properties 对象是怎么生成的,每个属性的值为什么会出现2次,那个属性的值的 key 是怎么生成的
    (判断属性是否过多是以 25为界限的)
    2020-03-21
    1
  • 一步
    老师有个疑问就是:当常规属性的数量大于对象内属性的数量10限制后,就会按照创建顺序先把常规属性放到对象内属性中,然后再把剩余的常规属性放到 properties 属性中,这样的话。当我查询一个常规属性的时候,就需要查询两次:先查询对象内属性,没有的话在查询 properties 属性。

    这里多查询了一次,为什么不这样设计呢? 当常规属性的数量大于对象内属性的数量10限制后就不使用对象内属性了,直接使用properties 属性,这样不就会减少一次查询吗?
    2020-03-21
    1
  • 一步
    字典存储模式,这样虽然降低了查找速度,但是却提升了修改对象的属性的速度。
    -----------------------------------------
    字段存储为了降低了查找效率呢? 字典不是 O(1), 直接就可以索引到的,是因为字段的 key 的 hash 有可能冲突吗?然后退化成链表?
    2020-03-21
    1
  • 潘启宝
    最新版本的chrome在Memory里执行后,跟你文章里不一样,可能是最新版本的更改里算法,你可以看看。
    2020-03-29
  • Geek_0ae489
    delete操作,在删除线性结构会有移动其他元素的耗时,如果删除的属性个数是介于对象内属性和常规属性properties之间,会触发结构调整,而且非线性结构查询也耗时
    2020-03-28
  • rainke
    所获取属性可能不是O(1)
    2020-03-26
  • -_-|||
    文中”10 属性直接存放在 bar2 的对象内 ;
    10 个常规属性以线性数据结构的方式存放在 properties 属性里面 ;”属性有冲突啊,比如property10即在bar2对象内,又在properties中。
    2020-03-26
  • Lorin
    老师,hash表和js中对象是什么关系?我感觉对象就是哈希表,但是我看哈希表的定义里面key会经过哈希函数进行编码,这之间有什么区别呢?
    2020-03-25
  • 早起不吃虫
    老师请教一个问题,node也是基于v8运行的,所以默认的运行内存是不是有限制?如何可以打开这个限制呢?有没有什么可以查看内存占用的调试工具?
    2020-03-24
  • Geek_619e80
    element和properties都是线性结构,为什么数字属性要排序而不按创建顺序?
    2020-03-24
  • 慢慢来的比较快
    因为delete 删除属性时,先查找在删除,删除后线性结构会出现间隙,要重新进行排序;不知道对不对
    2020-03-23
  • Longerian
    我在chrome里执行查看内存对象布局,搜索 Foo ,过滤出来的是空列表,这是为啥

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

    2020-03-23
    3
收起评论
31
返回
顶部