ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

浏览器学习笔记-08 v8基础

2020-09-20 16:33:58  阅读:215  来源: 互联网

标签:浏览器 对象 08 JavaScript 回收 区域 垃圾 v8 执行


V8

弱类型动态语言

JavaScript是一种弱类型动态语言

弱类型: 这说明在定义变量的时候不需要事先定义变量的类型,JavaScript在引擎在运行代码的时候会自己计算
动态:说明不同类型的变量可以相互赋值

栈空间和堆空间

在JavaScript的执行过程中,主要有三种内存空间:代码空间、栈空间和堆空间。

原始类型的数据值都是直接保存在“栈”中的,引用类型的值是存放在“堆”中的。

对象类型是存放在堆空间的,在栈空间中只是保留了对象的引用地址,当 JavaScript 需要访问该数据的时候,是通过栈中的引用地址来访问的

调用栈中的数据是如何回收的

记录当前执行状态的指针(称为 ESP),指向调用栈中的函数的执行上下文,表示当前正在执行的函数

当一个函数执行结束之后,JavaScript 引擎会通过向下移动 ESP 来销毁该函数保存在栈中的执行上下文。当下一个执行函数到来时,就会覆盖原有的栈空间。

堆中的数据是如何回收的

ESP 应该是指向全局执行上下文的,那这样的话,执行过的函数的执行上下文就处于无效状态了,不过保存在堆中的对象依然占用着空间。要回收堆中的垃圾数据,就需要用到 JavaScript 中的垃圾回收器了

代际假说和分代收集

代际假说(The Generational Hypothesis)的内容,这是垃圾回收领域中一个重要的术语,后续垃圾回收的策略都是建立在该假说的基础之上的,

代际假说有以下两个特点:

  • 第一个是大部分对象在内存中存在的时间很短,简单来说,就是很多对象一经分配内存,很快就变得不可访问;
  • 第二个是不死的对象,会活的更久。

在 V8 中会把堆分为新生代和老生代两个区域,新生代中存放的是生存时间短的对象,老生代中存放的是生存时间久的对象。

  新生区通常只支持 1~8M 的容量,而老生区支持的容量就大很多了。对于这两块区域,V8 分别使用两个不同的垃圾回收器,以便更高效地实施垃圾回收。

  • 副垃圾回收器,主要负责新生代的垃圾回收
  • 主垃圾回收器,主要负责老生代的垃圾回收

副垃圾回收器

副垃圾回收器主要负责新生代的垃圾回收。而通常情况下,大多数小的对象都会被分配到新生区,所以说这个区域虽然不大,但是垃圾回收还是比较频繁的。

  新生代中用 Scavenge 算法来处理。所谓 Scavenge 算法,是把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域,如下图所示:

  新加入的对象都会存放到对象区域,当对象区域快被写满时,就需要执行一次垃圾清理操作。
  在垃圾回收过程中,首先要对对象区域中的垃圾做标记;标记完成之后,就进入垃圾清理阶段,副垃圾回收器会把这些存活的对象复制到空闲区域中,同时它还会把这些对象有序地排列起来,所以这个复制过程,也就相对于完成了内存清理操作,复制后空闲区域就没有内存碎片了。
  完成复制后,对象区域与空闲区域进行角色翻转,也就是原来的对象区域变成空闲区域,原来的空闲区域变成了对象区域。这样就完成了垃圾对象的回收操作,同时这种角色翻转的操作还能让新生代中的这两块区域无限重复使用下去。

  由于新生代中采用的 Scavenge 算法,所以每次执行清理操作时,都需要将存活的对象从对象区域复制到空闲区域。但复制操作需要时间成本,如果新生区空间设置的太大了,那么每次清理的时间就会过久,所以为了执行效率,一般新生区的空间会被设置的比较小。

  也正是因为新生区的空间不大,所以很容易被存活的对象装满整个区域。为了解决这个问题,JavaScript 引擎采用了对象晋升策略,也就是经过两次垃圾回收依然还存活的对象,会被移动到老生区中。

主垃圾回收器

主垃圾回收器主要负责老生区中的垃圾回收。除了新生区中晋升的对象,一些大的对象会直接被分配到老生区。因此老生区中的对象有两个特点,一个是对象占用空间大,另一个是对象存活时间长。

由于老生区的对象比较大,若要在老生区中使用 Scavenge 算法进行垃圾回收,复制这些大的对象将会花费比较多的时间,从而导致回收执行效率不高,同时还会浪费一半的空间。因而,主垃圾回收器是采用 标记 - 清除(Mark-Sweep)的算法进行垃圾回收的。



多次执行标记 - 清除算法后,会产生大量不连续的内存碎片。而碎片过多会导致大对象无法分配到足够的连续内存,于是又产生了另外一种算法 —— 标记 - 整理(Mark-Compact),这个标记过程仍然与 标记 - 清除 算法里的是一样的,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

全停顿

现在你知道了 V8 是使用副垃圾回收器和主垃圾回收器处理垃圾回收的,不过由于 JavaScript 是运行在主程序之上的,一旦执行垃圾回收算法,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。我们把这种行为叫做全停顿(Stop-The-World)

为了降低老生代的垃圾回收而造成的卡顿,V8 将标记过程分为一个个的子标记过程,同时让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成,我们把这个算法称为 增量标记(Incremental Marking)算法。

编译执行

由于机器并不能直接识别我们的高级语言,必须将代码转换为机器能够识别的机器语言,按语言的执行流程,可以把语言分为 编译型语言和解释型语言

编译型语言在程序执行之前,需要经过编译器的编译过程,并且编译之后会直接保留机器能读懂的二进制文件,这样每次运行程序时,都可以直接运行该二进制文件,而不需要再次重新编译了 。比如 C/C++、GO 等都是编译型语言。

而由解释型语言编写的程序,在每次运行时都需要通过解释器对程序进行动态解释和执行。比如 Python、JavaScript 等都属于解释型语言

V8是怎么执行一段代码
整体流程如下:

标签:浏览器,对象,08,JavaScript,回收,区域,垃圾,v8,执行
来源: https://www.cnblogs.com/SLchuck/p/13700819.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有