V8的垃圾回收(v8的垃圾回收策略主要基于什么)
前言
利用周末的空闲时间,粗略翻了一下《深入浅出Node.js》,感觉这本书还是很有深度的,但是自己段位不够,对于node了解还是不多,还是了解一下对面试有用的垃圾回收机制吧。
V8的垃圾回收机制
为什么有垃圾回收机制,内存限制。在默认设置下,如果一直分配内存,在64位系统和32位系统下分别只能使用约1.4GB和0.7GB的大小。
垃圾回收包含调用栈的数据回收和堆的数据回收。调用栈的垃圾回收一般通过一个记录当前执行状态的指针(ESP),指针下移就是销毁函数执行上下文的过程。So,我们主要还是深度了解一下堆中的垃圾回收,也就是我们说的V8的垃圾回收机制。
V8的垃圾回收策略主要基于分代式垃圾回收机制(代际假说)。
大部分对象在内存中存在的时间很短
不死的对象活的更久
主要将内存分为新生代和老生代两代。
新生代
新生代:存放存活时间较短的对象采用Scavenger算法进行垃圾回收,一种采用复制的方式实现的垃圾回收算法。
它将堆内存一分为二,处于使用状态的空间称为From空间,处于闲置状态的空间称为To空间。
新创建的对象先分配在From空间,垃圾回收时,将From空间的存活对象复制到To空间,非存活对象占用的空间被释放
复制完成后,From空间和To空间的角色发生互换
该算法由于只复制存活对象,在频繁创建临时对象的场景,垃圾回收效率很高。
老生代
存活时间较长或常驻内存的对象。当一个对象经过多次复制依然存活时,这种对象会被移到老生代中,将采用新的算法进行垃圾回收。对象从新生代移动到老生代中的过程称为晋升。
对象晋升的条件满足下面一种即可:
1.对象是否经历过新生代复制
2.对象从From空间复制到To空间时,To空间已使用超过25%。
标记清除(mark-and-sweep)
老生代中的对象,不再适合Scavenger算法:一是存活对象多,复制效率低;二是空间一分为二浪费一半空间。
标记清除:在标记阶段,垃圾回收器会递归的标记到运行时每一个可访问的对象,清除阶段只清除没有标记的对象。但是标记清除带来一个问题是进行一次标记清除后,内存空间会出现不连续的状态,导致下一次分配大内存对象而放不下,所以引入了标记整理。
标记整理
在整理的过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界以外的内存。
增量标记
为了避免js应用逻辑和垃圾回收器看到的不一致,垃圾回收的3种算法都需要将应用逻辑暂停下来,待执行完垃圾回收再恢复执行应用逻辑,这种行为称为"全停顿"。老生代空间分配的很大,一次回收耗时会很长,这样将导致页面的卡顿。当然,这样行为是很早之前的方案。V8引入增量标记,也就是js应用逻辑和垃圾回收交替执行。
垃圾回收算法对比
在V8的回收策略中两者是结合使用的,下面是三种算法的比对
总结
面试官:你能说说V8的垃圾回收机制吗?
V8的垃圾回收的策略就是1.大部分对象存活很短2.不死的对象活的更多
堆内存分为新生代和老生代空间
新生代采用的scavenge算法,内存小,内存空间一分为二;垃圾回收时,将存活对象复制到空闲的一边,清除掉原先的空间。
老生代采用标记清除和标记整理算法。标记清除就是标记所有存活对象,清除掉未标记对象。然后留下了内存碎片,然后采用标记整理,将存活对象移动到一边,清理边界以外的内存。
最后
个人感觉这样纯理论性的文章,都是千篇一律,完整的借鉴了《深入浅出Node.js》,哈哈,不过写完一遍文章之后,我觉得面试再被问到这一块,高低能整上一句。所以,我们应该要多发文章,加油,(,,´•ω•)ノ"(´っω•`。)
伪原创工具 SEO网站优化 https://www.237it.com/
作者:竹业
链接:https://juejin.cn/post/7036005463946690590