浏览器原理:5.1 JS内存分析以及JS引擎的垃圾回收

首先得了解 JS 的数据类型是怎样的

JS 的数据类型

  • 基本数据类型
    - Number
    - String
    - Bool
    - Null
    - unidifined
    - Symbol
    - BigInt
  • 引用数据类型
    - Object

JS 有两大数据类型,基本数据类型,引用数据类型。

基本数据类型的变量就保存其原始值,而引用数据类型的变量保存其引用。

JS 的内存空间:堆区和栈区

和大多数高级语言一样,JS 的内存空间分为两大类,堆区和栈区,栈区即前面所说的执行栈,用来存放整个执行上下文,而 JS 的变量就存放在执行上下文中的变量环境或者词法环境中。堆区,可以理解成一个巨大的字符数组,JS引擎可以用它来存放一些变量值(主要是对象)。栈区中的引用数据的值存放指向堆区所对应的地址的引用,类似C/C++中的指针。

这样设计的优点在于,为用于存储JS变量的执行上下文节省了大部分的内存,让执行上下文切换效率大幅提高。众所周知JS依靠切换执行上下文来进行函数调用,函数返回值,即在JS执行过程中,一般是会进行大量的执行上下文切换的,如果执行上下文的内存过大,那么执行上下文的切换效率也会大幅降低,JS的运行性能也会大幅降低。

垃圾回收

在 C/C++ 中,new 和 malloc 是在堆区中创建变量。如果该变量不用了,因为是在堆区,如果程序员不自己主动去手动销毁,那么该变量会一直存在堆区中,从而造成内存泄漏。为了避免这种问题,JS引擎采取了垃圾回收这一机制,即由浏览器中的JS引擎来执行回收堆区的一些垃圾数据的操作。虽然JS采用了不由程序员负责垃圾回收这一决策,但还是有必要去具体了解JS引擎中的垃圾回收机制是怎样的,避免造成连垃圾回收都不能挽救的内存泄漏。下面主要介绍 V8 引擎的垃圾回收机制

代际假说和分代收集

  • 垃圾回收有这么一个假说 —— 代际假说,它主要有两个观点

    • 大部分对象在内存中存在的时间很短,即很多对象一经分配内存,很快就会变得不可访问
    • 不死的对象,会活得更久
  • 分代收集是 V8 引擎采用的 一种垃圾回收算法,该算法主要把堆区分成两个区域,新生代和老生代,对于这两个区域,分别采取两个不同的垃圾回收器,以便更高效地进行垃圾回收

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

垃圾回收器的工作流程

  • 第一步,标记,标记空间中活动对象和非活动对象
    • 活动对象:还在使用的对象
    • 非活动对象:可以被垃圾回收的对象
  • 第二步,回收,回收非活动对象占据的内存
  • 第三步,整理,做内存整理,因为一般来说,频繁回收对象后,内存中会存在内存碎片,即大量不连续的空间,这些内存碎片会让一些需要分配较大连续内存的数据(比如数组)造成内存不足的情况,所以做内存整理

副垃圾回收器

副垃圾回收器负责回收新生代,通常情况下,大多数下的对象都会被分配在新生代,区域不大,但垃圾回收比较频繁。

新生代区域分成两部分,空闲区域和对象区域,新加入的对象都会被放在对象区域中,当对象区域使用的内存达到一个阈值后,就会执行一次垃圾清理操作,在垃圾回收过程中,副垃圾回收器会把这些存活的对象复制到空闲区域中,同时还会将这些对象有序地排列起来,即内存整理

完成复制后,空闲区域和对象区域会角色互换,这样就完成了整个垃圾回收过程

一般来说,因为新生代区域经常执行垃圾回收,所以新生代区域的空间会被设置得比较下,但这也存在一个问题:万一新生代区域空间满了怎么办?针对这一点,JS引擎采用了对象晋升策略:经过两次垃圾回收依然存活的对象晋升到 老生代区域中。

主垃圾回收器

主垃圾回收器负责回收老生代,老生代中除了新生代晋升的对象以外,一些内存较大的对象会被直接分配在老生区中,即老生区中的对象要么大要么久

主垃圾回收器采取 标记-清楚 的算法进行垃圾回收

全停顿

因为 JS 的执行是在 JS引擎 中的 主线程上运行的,即一旦执行垃圾回收,都需要中断当前正在执行的 JS脚本,待垃圾回收完毕后再度恢复执行,这就是全停顿。

针对全停顿,V8 引擎采用增量标记算法,将标记过程分为一个个的子标记过程,同时让 垃圾回收标记 和 JS脚本 交替进行,直到标记阶段完成。将垃圾回收拆解成一个个小任务夹杂在JS脚本之间执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用中的错误信息,ImportError: liblua5.1.so: cannot open shared object file: No such file or directory,这个错误是由于缺少liblua5.1.so文件导致的。根据引用的建议,您可以尝试安装liblua5.1-0-dev来解决这个问题。您可以执行以下命令来安装该库: sudo apt install liblua5.1-0-dev 如果安装过程中出现其他错误,您可以尝试执行以下命令来修复依赖关系并重新安装: apt --fix-broken install 这样应该能够解决缺少liblua5.1.so文件的问题。希望对您有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [nginx出现 liblua5.1.so.0: cannot open shared object file:](https://blog.csdn.net/iohappyoi/article/details/117767608)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [rpm: error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such fi...](https://blog.csdn.net/weixin_34392843/article/details/86123500)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值