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 位的机器上,默认最大操作的对象大小约 ...
随机推荐
- JS generator(生成器)
笔记整理自:廖雪峰老师的JS教程 目录 简介 与函数的不同之处 函数写法 generator写法 generator调用 generator对象的`next()`方法调用 `for ... of`循环 ...
- C程序:年转化天
突然想算算自己到底活了多少天了,e,就是纯属为了好玩,毕竟咱作为一名C初学者还是要多练练的- 为了好玩,加了个密码登陆的,密码是521,还有就是不太懂时间获取... 具体闰年的判断方法: 代码如下: ...
- 企业级Docker容器镜像仓库Harbor的搭建
Harbor简述 Habor是由VMWare公司开源的容器镜像仓库.事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理 ...
- iOS中JavaScript和OC交互 --by 胡 xu
在iOS开发中很多时候我们会和UIWebView打交道,目前国内的很多应用都采用了UIWebView的混合编程技术,最常见的是微信公众号的内容页面.前段时间在做微信公众平台相关的开发,发现很多应用场景 ...
- Redis高可用(持久化、主从复制、哨兵、集群)
Redis高可用(持久化.主从复制.哨兵.集群) 目录 Redis高可用(持久化.主从复制.哨兵.集群) 一.Redis高可用 1. Redis高可用概述 2. Redis高可用策略 二.Redis持 ...
- 06 jQuery
BOM和DOM 1. 什么是BOM和DOM 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的 ...
- Linux基础:初识shell之系统命令基础
一 shell介绍 shell Shell 中文意思贝壳,寓意类似内核的壳.Shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务,简而言之就是只要能够操作应用 ...
- suse 12 二进制部署 Kubernetets 1.19.7 - 第13章 - 部署metrics-server插件
文章目录 1.13.0.创建metrics-server证书和私钥 1.13.1.生成metrics-server证书和私钥 1.13.2.开启kube-apiserver聚合配置 1.13.3.分发 ...
- mysq数据库相信介绍大纲!!!!!!
什么是数据库? 数据库(Database)是按照数据结构来安排.存储和办理数据的仓库. 每个数据库都有一个或多个不同的 API 用于创立,访问,办理,搜索和仿制所保存的数据. 我们也能够将数据存储在文 ...
- SpringBoot 自定义MessageConvert
创建一个MessageConvert类,实现HttpMessageConvert接口 简单实现,只完成写功能.其他默认false package com.boot.converter; import ...