图解 Google V8
李兵
前盛大创新院高级研究员
立即订阅
3273 人已学习
课程目录
已完结 24 讲
0/4登录后,你可以任选4讲全文学习。
宏观视角 (2讲)
开篇词 | 如何学习谷歌高性能 JavaScript 引擎V8?
免费
01 | V8是如何执行一段JavaScript代码的?
JavaScript设计思想篇 (7讲)
02 | 函数即对象:一篇文章彻底搞懂JavaScript的函数特点
03 | 快属性和慢属性:V8是怎样提升对象属性访问速度的?
04 | 函数表达式:涉及大量概念,函数表达式到底该怎么学?
05|原型链:V8是如何实现对象继承的?
06|作用域链:V8是如何查找变量的?
07|类型转换:V8是怎么实现1+“2”的?
08|答疑:如何构建和使用V8的调试工具d8?
V8编译流水线 (8讲)
09 | 运行时环境:运行JavaScript代码的基石
10 | 机器代码:二进制机器码究竟是如何被CPU执行的?
11 | 堆和栈:函数调用是如何影响到内存布局的?
12 | 延迟解析:V8是如何实现闭包的?
13 | 字节码(一):V8为什么又重新引入字节码?
14|字节码(二):解释器是如何解释执行字节码的?
15 | 隐藏类:如何在内存中快速查找对象属性?
16 | 答疑: V8是怎么通过内联缓存来提升函数执行效率的?
事件循环和垃圾回收 (6讲)
17 | 消息队列:V8是怎么实现回调函数的?
18 | 异步编程(一):V8是如何实现微任务的?
19|异步编程(二):V8是如何实现async/await的?
20 | 垃圾回收(一):V8的两个垃圾回收器是如何工作的?
21 | 垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
22|答疑:几种常见内存问题的解决策略
结束语 (1讲)
结束语 | 我的前端学习踩坑史
图解 Google V8
15
15
1.0x
00:00/00:00
登录|注册

15 | 隐藏类:如何在内存中快速查找对象属性?

李兵 2020-04-18
你好,我是李兵。
我们知道 JavaScript 是一门动态语言,其执行效率要低于静态语言,V8 为了提升 JavaScript 的执行速度,借鉴了很多静态语言的特性,比如实现了 JIT 机制,为了提升对象的属性访问速度而引入了隐藏类,为了加速运算而引入了内联缓存。
今天我们来重点分析下 V8 中的隐藏类,看看它是怎么提升访问对象属性值速度的。

为什么静态语言的效率更高?

由于隐藏类借鉴了部分静态语言的特性,因此要解释清楚这个问题,我们就先来分析下为什么静态语言比动态语言的执行效率更高。
我们通过下面两段代码,来对比一下动态语言和静态语言在运行时的一些特征,一段是动态语言的 JavaScript,另外一段静态语言的 C++ 的源码,具体源码你可以参看下图:
那么在运行时,这两段代码的执行过程有什么区别呢?
我们知道,JavaScript 在运行时,对象的属性是可以被修改的,所以当 V8 使用了一个对象时,比如使用了 start.x 的时候,它并不知道该对象中是否有 x,也不知道 x 相对于对象的偏移量是多少,也可以说 V8 并不知道该对象的具体的形状。
那么,当在 JavaScript 中要查询对象 start 中的 x 属性时,V8 会按照具体的规则一步一步来查询,这个过程非常的慢且耗时(具体查找过程你可以参考《03|快属性和慢属性:V8 是怎样提升对象属性访问速度的?》这节课程中的内容)。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《图解 Google V8》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(14)

  • 一步
    V8 有了隐藏了,所有的查询属性的操作都会走隐藏了吗? 这里除了内联缓存,还会走挨个遍历的属性的方法吗? 或者什么时候隐藏类会失效,退化为挨个遍历的属性 查找属性?
    2020-04-19
    3
  • 成楠Peter
    我想请教一个问题。用new Obejct和new Map创建有什么区别。Map有什么优化?
    2020-04-21
    2
    2
  • 文蔺
    最后的思考题,答案应该是使用『内联缓存』吧。我找到了一篇讲内联缓存的文章,挺好的 https://blog.csdn.net/szengtal/article/details/72861133

    作者回复: 是的,思考题是关于内联缓存策略的

    2020-04-18
    2
  • 我来人间一趟
    老师 我有个疑问 通过你给的截图 用delete删除一个属性的时候 隐藏类map的地址并没有变呀 只不过是properties的地址变了 这是怎么回事呀
    2020-05-08
    1
    1
  • 潇潇雨歇
    使用缓存,执行loadX,将其隐藏类缓存起来,再一次调用直接从缓存里查找对象。
    2020-04-19
    1
  • Longerian
    第3节已经提到了动态添加的数据利用elements 属性和 properties 属性提升属性的访问速度了,本文又介绍了隐藏类,那么有了隐藏类,还需要 elements 属性和 properties 属性的机制吗?
    2020-04-19
    1
  • 王楚然
    思考题:
    能调用loadX方法的对象,都需要有x属性。可不可以直接把x属性地址缓存起来,每次不必通过隐藏类去查找?
    2020-04-18
    1
  • 子云
    我有个疑问呀,从上文d8 print 打印出来的 ` point = {x:100,y:200};` 结构里的 map,我找不到哪里有偏移量的字段呀?

    ```
    0x19dc08284d11: [Map]
     - type: JS_OBJECT_TYPE
     - instance size: 20
     - inobject properties: 2
     - elements kind: HOLEY_ELEMENTS
     - unused property fields: 0
     - enum length: invalid
     - stable_map
     - back pointer: 0x19dc08284ce9 <Map(HOLEY_ELEMENTS)>
     - prototype_validity cell: 0x19dc081c0451 <Cell value= 1>
     - instance descriptors (own) #2: 0x19dc080c5b25 <DescriptorArray[2]>
     - prototype: 0x19dc08241151 <Object map = 0x19dc082801c1>
     - constructor: 0x19dc0824116d <JSFunction Object (sfi = 0x19dc081c55ad)>
     - dependent code: 0x19dc080401ed <Other heap object (WEAK_FIXED_ARRAY_TYPE)>
     - construction counter: 0
    ```
    2020-05-27
  • Aaaaaaaaaaayou
    “有了 map 之后,当你再次使用 point.x 访问 x 属性时,V8 会查询 point 的 map 中 x 属性相对 point 对象的偏移量,然后将 point 对象的起始位置加上偏移量,就得到了 x 属性的值在内存中的位置,有了这个位置也就拿到了 x 的值,这样我们就省去了一个比较复杂的查找过程。” 但是去隐藏类里面查找 x 这个属性还是得查找吧,这里又是怎么优化的呢?
    2020-05-18
  • 大力
    老师,我有个疑问:

    文中介绍了,隐藏类包含有以下信息:
    1.对象中所包含的所有的属性;
    2.“每种类型”相对于对象的偏移量。

    这里第二点的“每种类型”是不是应该为”每个属性“?

    作者回复: 是的,你这个说法合理点,我改正过来

    2020-05-15
  • 王子晨
    老师我有2个疑问,当访问对象属性时,先通过隐藏类map来获取该属性的偏移地址,然后在通过偏移地址去快慢属性中查找该属性的值或者指针么?第二问题是对象中得内属性也是先通过map查找还是直接访问内属性?
    2020-04-29
  • yunplane
    隐藏类中的偏移量都是针对对象的属性是数值的情况吧?如果对象的属性是字符串或者函数呢?
    2020-04-22
  • 一步
    什么情况下两个对象的形状是相同的,要满足以下两点:
    相同的属性名称
    相等的属性个数

    这里还要要求:相同的属性顺序吧
    2020-04-19
    1
  • 文蔺
    有个问题,例子中d8打印出来的 x/y 这俩字段为什么是在properties里面?按照第三讲,x和y不应该是快属性吗。可能是我理解不到位,烦请老师解惑

    作者回复: 因为是动态添加的,如果你一次把所有属性都写进字面量,就是快属性了

    2020-04-18
    1
收起评论
14
返回
顶部