| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> JavaScript垃圾回收机制 -> 正文阅读 |
|
[JavaScript知识库]JavaScript垃圾回收机制 |
JavaScript垃圾回收机制1 垃圾为何要产生并回收当我们写代码时创建一个基本类型、对象、函数等,都是需要占用内存的,JavaScript基本数据类型存储在栈内存中,引用数据类型存储在堆内存中,但是引用数据类型会在栈内存中存储一个实际对象的引用。 比如说我们创建了一个
那么原本堆内存给 2 垃圾回收机制JavaScript中主要的内存管理概念是可达性。 那什么是可达性呢,比如说定义一个对象:
如果将 那么JavaScript的垃圾回收就是定期找出这些不可达的对象,然后将其释放。那么找出这些不可达的对象有两种常用的策略:
2.1 标记清除法标记清除法分为标记和清除两个阶段,标记阶段需要从根节点遍历内存中的所有对象,并为可达的对象做上标记,清除阶段则把没有标记的对象(非可达对象)销毁。 标记清除法的优点就是实现简单。 它的缺点有两个,首先是内存碎片化。这是因为清理掉垃圾之后,未被清除的对象内存位置是不变的,而被清除掉的内存穿插在未被清除的对象中,导致了内存碎片化。 标记清除算法改进—— 标记整理算法标记清除算法的缺点主要在于内存清理之后剩余的内存位置不变而导致内存碎片化,因此可以使用标记整理算法改进。 标记整理算法的标记阶段与标记清除算法相同,都是从根节点遍历内存中的所有对象,为可达的对象打上一个标记。但是在标记结束后,标记整理算法将这些可达的对象移向内存的一端,然后清理掉边界的内存。 2.2 引用计数法引用计数法主要记录对象有没有被其他对象引用,如果没有被引用,它将被垃圾回收机制回收。它的策略是跟踪记录每个变量值被使用的次数,当变量值引用次数为0时,垃圾回收机制就会把它清理掉。 示例代码如下:
引用计数法的优点是可以实现立即进行垃圾回收。当引用计数在引用值为0时,立即进行垃圾回收,这样可以达到立刻垃圾回收的效果。 它的缺点也有两个,首先它需要一个计数器,这个计数器可能要占据很大的位置,因为我们无法知道被引用数量的多少。 第二个缺点是无法解决当出现循环引用时无法回收的问题。例如
3 V8对垃圾回收机制的优化——分代式垃圾回收机制目前大多数浏览器都是基于标记清除算法,V8进行了一些优化加工处理,采用分代式垃圾回收机制。 3.1 新生代与老生代原本的垃圾回收机制在每次回收时都要检查内存中所有的对象,这样的话,一些大、老、存活时间长的对象与新、小、存活时间短的对象检查频率相同,但是前者并不需要频繁进行清理,因此采用分代式垃圾回收机制。 V8中将堆内存分为新生代和老生代两区域,采用不同的垃圾回收策略进行回收。新生代的对象为存活时间较短的对象,通常只支持1~8M的容量,老生代的对象为存活时间较长或常驻内存的对象,容量通常比较大,V8整个堆内存的大小就等于新生代加上老生代的内存。 3.2 新生代的垃圾回收新生代垃圾回收策略中,将堆内存一分为二,一个是处于使用状态的使用区,一个是处于闲置状态的空闲区。 新生代回收策略——并行回收JavaScript是单线程的语言,当执行垃圾回收时,就会阻塞JavaScript脚本的执行,垃圾回收结束后再继续JavaScript脚本执行,这种情况叫做全停顿(Stop-The-World)。 如果执行一次垃圾回收需要100ms,那么脚本执行就得暂停100ms,如果执行垃圾回收的时间过长,那么就会造成页面卡顿,带来不好的用户体验。对于这样的情况,可以采用并行回收的策略。 并行回收指的是在主线程进行垃圾回收时,同时开启多个辅助线程一起执行垃圾回收。比如说一项任务一个人需要30天才能完成,那么如果安排两个人甚至多个人,可能10来天甚至更短的时间就完成了。实现并行回收可以大大降低垃圾回收的暂停时间。 新生代对象空间就采用并行策略,在执行垃圾回收的过程中,会启动了多个线程来负责新生代中的垃圾清理操作,这些线程同时将对象空间中的数据移动到空闲区域,这个过程中由于数据地址会发生改变,所以还需要同步更新引用这些对象的指针,此即并行回收。 3.3 老生代的垃圾回收老生代的垃圾回收操作主要就是标记清除算法的步骤了,在标记阶段标记所有的可达对象,清除阶段清除掉未被标记的对象。又由于该算法会出现内存碎片的问题,因此会使用标记整理算法来优化这个过程。 老生代回收策略——增量标记与惰性清理①增量标记增量就是将一次标记的过程,分成了许多次,每执行完一次就让应用逻辑执行一会儿,这样交替多次后完成垃圾回收。但是这会随之而来新的问题,首先是如何暂停每次标记去执行JavaScript代码,还有如果标记好的对象在执行js中改变了状态成为了可达或者不可达对象怎么办,V8对这两个问题对应的解决方案分别是三色标记法与写屏障。 a.三色标记法三色标记法使用三种颜色白、灰、黑来标记对象的状态。白色表示初始状态,黑色表示已检查状态,灰色表示待检查状态。 它的过程为: 采用三色标记法后,程序在恢复执行时可以直接判断当前内存中有没有灰色节点,如果有灰色节点,那么从灰色节点开始继续执行,如果没有,直接进入垃圾清理阶段。 b.写屏障写屏障可以解决第二个问题,如果执行任务程序时内存中标记好的对象引用关系被修改了,比如说黑色对象引用了白色对象,那么它就会将白色对象改成灰色对象,这样就可以保证下一次标记时可以正常进行。 ②惰性清理增量标记完成后,就开始清除垃圾。如果当前的可用内存可以支持快速的执行代码,就没必要立即清理内存,而且清理时没必要一次性清理完,可以按需清理。 优点:大大减少了主线程停顿的时间,让用户与浏览器交互的过程变得更加流畅 老生代回收策略——并发回收并发回收指的是主线程在执行JavaScript的过程中,辅助线程能够在后台完成执行垃圾回收的操作,辅助线程在执行垃圾回收的时候,主线程也可以自由执行 本文学习自掘金大佬 isboyjc 的文章:「硬核JS」你真的了解垃圾回收机制吗 |
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 22:58:46- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |