V8 引擎的垃圾回收机制
V8 引擎将内存分为新生代和老生代
由于不同对象的生存周期不同,只用一种回收策略来解决问题,这样效率会很低。所以V8采用了一种代回收的策略,将内存分为两个生代:新生代(new generation)和老生代(old generation)。
新生代:新创建的或只经历过一次垃圾回收的对象。
- 特点:大多数的对象被分配在这里,这个区域很小但是垃圾回特别频繁。
老生代:经历过多次垃圾回收的对象。
- 特点:所保存的对象大多数是生存周期很长的甚至是常驻内存的对象,而且老生代占用的内存较多。
如何判断是否可以被回收:
标记清除
当函数中声明一个变量时,就将这个变量标记为“进入环境”。而当变量离开环境时,则将其标记为“离开环境”。
首先,垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(可以使用任何标记方式)。
然后,它会去掉运行环境中的变量以及被环境中变量所引用的变量的标记。
此后,依然有标记的变量就被视为准备删除的变量,原因是在运行环境中已经无法访问到这些变量了。
最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。
引用计数
引用计数的垃圾收集策略不太常见。含义是跟踪记录每个值被引用的次数。
当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。
如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,改变了引用对象,则该值引用次数减1。
当这个值的引用次数变成0时,则说明没有办法再访问这个值了,在垃圾收集器下次再运行时,它就会释放内存。
垃圾回收算法:
新生代为存活时间较短的对象,老生代为存活时间较长或常驻内存的对象,分别对新老生代采用不同的垃圾回收算法来提高效率。
新生代垃圾回收算法
新生代使用Scavenge算法进行回收。在Scavenge算法的实现中,主要采用了Cheney算法。
Cheney算法算法是一种采用复制的方式实现的垃圾回收算法。新生代的空间被分为To和From空间。To一般是闲置的,对象都被存放在From空间,当From空间满了就会执行Scavenge 算法进行垃圾回收。当开始进行垃圾回收算法时,会检查From空间中的存活对象,这些存活对象将会被复制到To空间中(复制完成后会进行紧缩),而非活跃对象占用的空间将会被释放。完成复制后,From空间和To空间的角色发生对换。也就是说,在垃圾回收的过程中,就是通过将存活对象在两个semispace之间进行复制。可以很容易看出来,使用Cheney算法时,总有一半的内存是空的。但是由于新生代很小,所以浪费的内存空间并不大。而且由于新生代中的对象绝大部分都是非活跃对象,需要复制的活跃对象比例很小,所以其时间效率十分理想。
老生代垃圾回收算法
老生代占用内存较多(64位为1.4GB,32位为700MB),如果使用Scavenge算法,浪费一半空间不说,复制如此大块的内存消耗时间将会相当长。所以Scavenge算法显然不适合。V8在老生代中的垃圾回收策略采用Mark-Sweep和Mark-Compact相结合。
Mark-Sweep(标记清除)
标记清除分为标记和清除两个阶段。在标记阶段需要遍历堆中的所有对象,并标记那些活着的对象,然后进入清除阶段。在清除阶段总,只清除没有被标记的对象。由于标记清除只清除死亡对象,而死亡对象在老生代中占用的比例很小,所以效率较高。
标记清除有一个问题就是进行一次标记清除后,内存空间往往是不连续的,会出现很多的内存碎片。如果后续需要分配一个需要内存空间较多的对象时,若所有的内存碎片都不够用,将会使得V8无法完成这次分配,提前触发垃圾回收。
Mark-Compact(标记整理)
标记整理正是为了解决标记清除所带来的内存碎片的问题。标记整理在标记清除的基础进行修改,将其的清除阶段变为紧缩极端。在整理的过程中,将活着的对象向内存区的一段移动,移动完成后直接清理掉边界外的内存。紧缩过程涉及对象的移动,所以效率并不是太好,但是能保证不会生成内存碎片。
在V8的回收策略中,Mark-Sweep和Mark-Conpact两者是结合使用的。主要使用标记清除,在空间不足以对从新生代中晋升过来的对象进行分配时,才使用标记整理。
对象的晋升:
当一个对象满足某些条件,就会被移动到老生代,这称为对象的晋升。具体标准有两种:
判断是对象否已经经过一次 Scavenge 回收。若经历过,则将对象从 From 空间复制到老生代中;若没有经历,则复制到 To 空间。
其次判断To 空间的内存使用占比是否超过限制。当对象从 From 空间复制到 To 空间时,若 To 空间使用超过 25%,对象直接晋升到老生代中。设置 25% 的原因主要是因为两个空间会交换位置,如果 To 空间的内存太小,会影响后续的内存分配。
总结:
V8的垃圾回收机制分为新生代和老生代。
新生代主要使用Scavenge进行管理,将内存平均分为两块,使用的叫From空间,闲置的叫To空间。新对象都先分配到From空间中,回收时先判断是否存活,如果存活将存活对象复制到To空间中,清空From的内存空间后,再调换From空间和To空间,继续进行内存分配。且满足晋升条件时对象会从新生代晋升到老生代。
老生代主要采用Mark-Sweep和Mark-Compact算法,一个是标记清除,一个是标记整理。两者不同的地方是,标记清除在垃圾回收后会产生碎片内存,而标记整理在清除前会进行一步整理,将存活对象向一侧移动,随后清空边界的另一侧内存,这样空闲的内存都是连续的,但速度会慢一些。在V8中,老生代是标记清除和标记管理共同进行管理的。
由于在进行垃圾回收的时候会暂停应用的逻辑,对于新生代方法由于内存小,每次停顿的时间不会太长,但对于老生代来说每次垃圾回收的时间长,停顿会造成很大的影响。为了解决这个问题 V8 引入了增量标记的方法,将一次停顿进行的过程分为了多步,每次执行完一小步就让运行逻辑执行一会,就这样交替运行。
V8 引擎的垃圾回收机制的更多相关文章
- 一文搞懂V8引擎的垃圾回收
引言 作为目前最流行的JavaScript引擎,V8引擎从出现的那一刻起便广泛受到人们的关注,我们知道,JavaScript可以高效地运行在浏览器和Nodejs这两大宿主环境中,也是因为背后有强大的V ...
- V8引擎的垃圾回收策略
V8 的垃圾回收策略主要基于分代式垃圾回收机制.所谓分代式,就是将内存空间分为新生代和老生代两种,然后采用不同的回收算法进行回收. 新生代空间 新生代空间中的对象为存活时间较短的对象,大多数的对象被分 ...
- V8 下的垃圾回收机制
V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 1.新生代算法 新生代中的对象一般存活时间较短,使用 Scavenge GC 算法. ...
- 浅谈Chrome V8引擎中的垃圾回收机制
垃圾回收器 JavaScript的垃圾回收器 JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带 ...
- 浅谈V8引擎中的垃圾回收机制
最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...
- Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略
V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 一.前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存.垃圾 ...
- v8垃圾回收和js垃圾回收机制
垃圾回收器是一把十足的双刃剑.好处是简化程序的内存管理,内存管理无需程序员来操作,由此也减少了长时间运转的程序的内存泄漏.然而无法预期的停顿,影响了交互体验.本文从 V8 (node.js runti ...
- 超详细的node/v8/js垃圾回收机制
前言 垃圾回收器是一把十足的双刃剑.其好处是可以大幅简化程序的内存管理代码,因为内存管理无需程序员来操作,由此也减少了(但没有根除)长时间运转的程序的内存泄漏.对于某些程序员来说,它甚至能够提升代码的 ...
- V8 内存管理和垃圾回收机制总结
这篇文章主要介绍 V8 的内存管理和垃圾回收知识. V8 内存管理及垃圾回收机制浅析 由于 V8 引擎的原因,Node 在操作大内存对象时受到了一些限制,在 64 位的机器上,默认最大操作的对象大小约 ...
随机推荐
- Java中的增强型for循环
下面是关于增强型for循环对一维数组与二维数组遍历的具体实现: public class NewForLoop { public static void main(String[] args) { i ...
- Ajax创建对象的方法
ajax涉及的技术包括Html.css.dom.xml.javascript等. 主流创建ajax对象的方法: IE6以下版本浏览器创建ajax对象方法是: 定义一个方法创建ajax对象:
- linux安装python3.6.6和新建虚拟环境
基础准备 修改本地时区 cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 安装epel yum源 yum -y install epel- ...
- byte溢出栗子
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11634402.html byte溢出测试: byte b1 = (byte) 127; byt ...
- python基础语法_10错误与异常
Python有两种错误很容易辨认:语法错误和异常. 语法错误 Python 的语法错误或者称之为解析错,是初学者经常碰到的,如下实例 异常 即便Python程序的语法是正确的,在运行它的时候,也有可能 ...
- Diary / Solution Set -「WC 2022」线上冬眠做噩梦
大概只有比较有意思又不过分超出能力范围的题叭. 可是兔子的"能力范围" \(=\varnothing\) qwq. 「CF 1267G」Game Relics 任意一个 ...
- 如何在 Flutter 中集成华为云函数服务
介绍 云函数是一项 Serverless 计算服务,提供 FaaS(Function as a Service)能力,可以帮助开发者大幅简化应用开发与运维相关事务,降低应用功能的实现门槛,快速构建业务 ...
- 大厂晋升指南:材料准备,PPT 写作和现场答辩
大部分公司在年初,都是绩效回顾.晋升答辩的时期,对于阿里.美团等不少互联网企业,财年是从前一年的 4 月到第二年的 3 月底,春节回来以后,就是一年一度的述职晋升环节. 这里我结合自己述职以及辅导其他 ...
- python爬虫:爬虫的简单介绍及requests模块的简单使用
python爬虫:爬虫的简单介绍及requests模块的简单使用 一点点的建议: (学习爬虫前建议先去了解一下前端的知识,不要求很熟悉,差不多入门即可学习爬虫,如果有不了解的,我也会补充个一些小知识. ...
- 『无为则无心』Python面向对象 — 54、重写和super()函数
目录 1.重写 2.super()函数 方式一 方式二 __mro__内置类属性说明 1.重写 在子类中如果有和父类同名的方法,则通过子类实例去调用该方法时,会调用子类中的该方法而不是父类的方法,这个 ...