垃圾回收是如何工作的
==========
要搞清楚垃圾回收是如何工作的,需要先了解一些基本概念。
基本概念
====
-
常驻集大小(resident set size):NodeJS 进程运行时占据的内存大小,通常包含:代码、栈和堆。
-
栈(stack):包含原始类型数据和指向对象的引用数据。栈中保存着局部变量和指向堆上对象的指针或定义应用程序控制流的指针(比如函数调用等)。下面代码中,a 和 b 都保存在栈中。function add (a, b) { return a + b } add(4, 5)
-
堆(heap):存放引用类型数据,比如对象、字符串、闭包等。下面代码中,创建的 Car 对象会被保存在堆中。function Car (opts) { this.name = opts.name } const LightningMcQueen = new Car({name: ‘Lightning McQueen’}) 对象创建后,堆内存状态如下:现在我们添加更多的对象:const SallyCarrera = new Car({name: ‘Sally Carrera’}) const Mater = new Car({name: ‘Mater’}) 堆内存状态如下:如果现在执行垃圾回收,没有任何内存会被释放,因为每个对象都在被使用(可到达)。现在我们修改代码,如下:function Engine (power) { this.power = power } function Car (opts) { this.name = opts.name this.engine = new Engine(opts.power) } let LightningMcQueen = new Car({name: ‘Lightning McQueen’, power: 900}) let SallyCarrera = new Car({name: ‘Sally Carrera’, power: 500}) let Mater = new Car({name: ‘Mater’, power: 100}) 堆内存状态变成:如果我们不在使用 Mater 的话,通过 Mater = undefined 删除了对内存中对象的引用,则内存状态变化为:此时内存中的 Mater 不再被其他对象使用了(不可达),当垃圾回收运行的时候,Mater 对象会被回收,其占据的内存会被释放。
-
对象的浅层大小(shallow size of an object):对象本身占据的内存大小。
-
对象的保留大小(retained size of an object):删除对象及其依赖对象后释放的内存大小
垃圾回收器是如何工作的
===========
NodeJS 的垃圾回收通过 V8 实现。大多数对象的生命周期都很短,而少数对象的寿命往往更长。为了利用这种行为,V8 将堆分成两个部分,年轻代(Young Generation)和老年代(Old Generation)。
年轻代
===
新的内存需求都在年轻代中分配。年轻代的大小很小,在 1 到 8 MB 之间。在年轻代中内存分配非常便宜,V8 在内存中会逐个为对象分配空间,当到达年轻代的边界时,会触发一次垃圾回收。
V8 在年轻代会采用 Scavenge 回收策略。Scavenge 采用复制的方式进行垃圾回收。它将内存一分为二,每一部分空间称为 semispace。这两个空间,只有一个空间处于使用中,另一个则处于闲置。使用中的 semispace 称为 「From 空间」,闲置的 semispace 称为 「To 空间」。
年轻代的内存分配过程如下:
-
从 From 空间分配对象,若 semispace 被分配满,则执行 Scavenge 算法进行垃圾回收。
-
检查 From 空间中的对象,若对象可到达,则检查对象是否符合提升条件,若符合条件则提升到老生代,否则将对象从 From 空间复制到 To 空间。
-
若对象不可到达,则释放不可到达对象的空间。
-
完成复制后,将 From 空间与 To 空间进行角色翻转(flip)。
在年轻代中幸存的对象会被提升到老年代。
老年代
===
老年代中的对象有两个特点,第一是存活对象多,第二个存活时间长。若在老年代中使用 Scavenge 算法进行垃圾回收,将会导致复制存活对象的效率不高,且还会浪费一半的空间。因此在老年代中,V8 通常采用 Mark-Sweep 和 Mark-Compact 策略回收。
Mark-Sweep 就是标记清除,它主要分为标记和清除两个阶段。
-
标记阶段,将遍历堆中所有对象,并对存活的对象进行标记;
-
清除阶段,对未标记对象的空间进行回收。
与 Scavenge 策略不同,Mark-Sweep 不会对内存一分为二,因此不会浪费空间。但是,经历过一次 Mark-Sweep 之后,内存的空间将会变得不连续,这样会对后续内存分配造成问题。比如,当需要分配一个比较大的对象时,没有任何一个碎片内支持分配,这将提前触发一次垃圾回收,尽管这次垃圾回收是没有必要的。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
![](https://img-blog.csdnimg.cn/img_convert/2d090d6da107f2f68fad7af5b87b5e91.jpeg)
核心竞争力,怎么才能提高呢?
成年人想要改变生活,逆转状态?那就开始学习吧~
万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。
为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。
前端面试题汇总
JavaScript
性能
linux
前端资料汇总
完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了。
前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。
.png)
完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了。
前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。