一文读懂V8垃圾回收机制——新生代Scavenge、老生代Mark-Sweep和Mark-Compact
1 V8内存管理
1.1 V8n内存限制
- 64位系统可用1.4G内存
- 32位系统可用0.7G内存
1.2 V8内存管理
- JS对象都是通过V8进行分配管理内存的
- process.memoryUsage()返回一个对象,包含了Node进程的内存占用信息
console.log(process.memoryUsage());//结果如下:{rss: 19550208, // 所有内存占用,包括指令区和堆栈heapTotal: 5533696, // “堆”占用的内存,包括用到的和没用到的heapUsed: 2645088, // 用到的堆的部分。判断内存泄漏,以heapUsed字段为准external: 778349 // V8引擎内部的C++对象占用的内存}
- 所有内存占用结构图:
------------------------------------------| || Resident Set 所有内存占用 || || ---------------------------- || | 代码区域 Code Segment | || ---------------------------- || || ---------------------------- || | 栈(Stack):本地变量、指针 | || ---------------------------- | | || ---------------------------- || | HeapTotal(堆):对象,闭包 | || | | || | --------------------- | | | | |heapUsed 使用到的堆。| | | | | | 判断内存泄漏, | | || | | 以heapUsed字段为准| | || | --------------------- | | | | | || ---------------------------- |------------------------------------------
- 上图举例:
var a = {name:‘yuhua’};这句代码会做如下几步:
- 将这句代码放入“代码区域 Code Segment”
- 将变量a放入“栈(Stack):本地变量、指针”
- 将{name:‘yuhua’}放入“HeapTotal(堆):对象,闭包”
注意:基本数据类型都在栈中,引用类型都在堆中
1.3 为何限制内存大小
- 因为V8垃圾收集工作原理导致的,1.4G内存完全一次垃圾收集需要1s以上
- 这个垃圾回收这段时间(暂停时间)成为Stop The World,在这期间,应用的性能和响应能力都会下降
1.4 如何打开内存限制
- 一旦初始化成功,生效后不能修改
- -max-new-space-size 最大 new space 大小,执行scavenge回收,默认16M,单位KM
- -max-old-space-size,最大 old space 大小,执行MarkSweep回收,默认1G,单位MB
2.V8的垃圾回收机制
- V8是基于分代的垃圾回收
- 不同代垃圾回收机制也不一样
- 按存货的时间分为新生代和老生代
2.1 分代
- 年龄小的是新生代,由From区域和To区域两个区域组成
- 在64位系统里,新生代内存是32M,From区域和To区域各占16M
- 在32位系统里,新生代内存是16M,From区域和To区域各占8M
- 年龄大的是老生代,默认情况下:
- 64位系统下老生代内存是1400M
- 32位系统下老生代内存是700M
2.2 新生代的垃圾回收(新生代GCGC)
2.2.1 过程
- 新生代区域一分为二,每个16M,一个使用,一个空闲
- 开始垃圾回收的时候,会检查FROM区域中的存活对象,如果还活着,拷贝到TO空间,所有存活对象拷贝完后,清空(释放)FROM区域
- 然后FROM和To区域互换
2.2.2 特点
新生代扫描的时候是一种广度优先的扫描策略
- 什么叫做广度优先的扫描策略?这里涉及到扫描指针跟分配指针
- 举例:
- 假设全局变量下的变量A引用了变量B和变量C,变量B引用了变量D,变量E没被引用
ROOT↓A E↓→ → →↓ ↓B C↓D
- 那么在to区域,存在一个扫描指针和分配指针,起初都指向最开始
- 然后A发现被全局引用,那么A拷贝到to区域,这时候扫描指针指向A,分配指针指向后面一位
A↑ ↑SM FP
- 然后A又引用了B,这时候把B拷贝到to区域,放在A后面,扫描指针还是指向A,分配指针往后移动一位
A B↑ ↑SM FP
- 然后再看A又引用了C,这时候把C拷贝到to区域,放在B后面,扫描指针还是指向A,分配指针往后移动一位
A B C ↑ ↑SM FP
- 然后发现A没有引用其他了,那将扫描指针往后移动一位指向B
A B C↑ ↑SM FP
- 然后发现B没有引用其他了,那再将扫描指针往后移动一位指向C
A B C↑ ↑SM FP
- 然后C也没有引用其他了,还剩下D,D不存在引用,所以不需要移动到to区域,这时候清空FROM区域,然后将FROM和To交换。
- 这就完成了一次垃圾回收。
- 举例:
- 什么叫做广度优先的扫描策略?这里涉及到扫描指针跟分配指针
新生代的空间小,存活对象少
当一个对象经理多次的垃圾回收依然存活的时候,生存周期比较差的对象会被移动到老声带,这个移动过程被称为晋升或升级
- 经历过5次以上的回收还存在
- TO的空间使用占比超过25%,或者超大对象
浏览器的memory中可以通过拍快照看变量是否被垃圾回收
置为undefined 或 null 都能将引用计数减去1
2.2.3 举例
- 例一:
function Person(){this.name = name;}let p1 = new Person('yuhua1');// 引用计数为1let p2 = new Person('yuhua2');// 引用计数为1// p1 p2 不会被自动销毁,因为全局(虽然是let),如果是局部,会自动销毁
- 例二:
function Person(){this.name = name;}let p1 = new Person('yuhua1');// 引用计数为1let p2 = new Person('yuhua2');// 引用计数为1setTimeout(function(){p1 = null;// 3秒后引用计数减1,变成0,就销毁,}, 3000)setTimeout(function(){p1 = null;// 10秒后引用计数减1,变成0,就销毁,}, 10000)
- 例三:
function Person(name){this.name = name;}let set = new Set();let p1 = new Person('yuhua');//引用计数为1set.add(p1);//引用计数为2p1 = null;//引用计数减1,为1,并不会销毁,虽然p1确实变为null了//这时候怎么销毁p1,不能再将p1置为null,这是没用的。由于p1是被set引用,所以应该将set销毁,这样才能销毁p1set = null;//这时候p1引用计数减1,为0,销毁。同时set引用计数也为0,也销毁了
- 例四:
function Person(name){this.name = name;}let PersonFactory = function(name){let p = new Person(name);return function(){console.log(p);}}let p1 = PersonFactory('zfpx');// 这里的p引用计数为1p1();//这里的p引用计数为2
2.3 老生代的垃圾回收策略
2.3.1 基础
- 老生代垃圾回收策略分为两种
- mark-sweep 标记清除
- 标记活着的对象,虽然清楚在标记阶段没有标记的对象,只清理死亡对象
- 会出现的问题:清除后内存不连续,碎片内存无法分配
- mark-compact 标记整理
- 标记死亡后会对对象进行整理,活着的左移,移动完成后清理掉边界外的内存(死亡的对象)
- mark-sweep 标记清除
- 老生代空间大,大部分都是活着的对象,GC耗时比较长
- 在GC期间无法想听,STOP-THE-WORLD
- V8有一个优化方案,增量处理,把一个大暂停换成多个小暂停 INCREMENT-GC
- 也就是把大暂停分成多个小暂停,每暂停一小段时间,应用程序运行一会,这样垃圾回收和应用程序交替进行,停顿时间可以减少到1/6左右
2.3.2 过程
假设有10个大小的内存,内存占用了6个,
- Mark-Sweep模式垃圾回收:
- 那么会给每个对象做上标记:如下图
A b C d E f 空 空 空 空//对上面每个对象做上标记,大写表示活着,小写表示死了//这时候,会存在一个问题,就是内存碎片无法使用,因为小写的内存没有跟后面空空空空的内存放在一起,不能使用
- 这时候小写(死)的都会被干掉,只保留大写(活)的,导致的问题就是内存碎片无法使用
- Mark-Compact模式垃圾回收:
- 将活的左移
A C E b d f 空 空 空 空
- 然后回收死了的区域
A C E 空 空 空 空 空 空 空
2.4 三种垃圾回收算法对比
回收算法 | Mark-Sweep | Mark-Compact | Scavenge |
---|---|---|---|
速度 | 中等 | 最慢 | 最快 |
空间开销 | 少 | 少 | 双倍空间(无碎片) |
是否移动对象 | 否 | 是 | 是 |
- V8老生代主要用Mark-Sweep,因为Mark-Compact需要移动对象,执行速度不快。空间不够时,才会用Mark-Compact
一文读懂V8垃圾回收机制——新生代Scavenge、老生代Mark-Sweep和Mark-Compact相关推荐
- 一文读懂Java 垃圾回收机制
什么是自动垃圾回收? 自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制. 所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象:而未使用中的对象(未 ...
- Node.js 内存管理和 V8 垃圾回收机制
作者:五月君 链接:https://www.imooc.com/article/288799 来源:首发慕课网 本文已获作者 "五月君" 授权转载,原文首发于 "慕课网& ...
- 深入理解谷歌最强V8垃圾回收机制
有很多人都听说过V8引擎,但可能不是很了解,V8名称叫Chrome V8,是由谷歌开源的一个高性能 JavaScript 引擎.该引擎采用 C++ 编写,Google Chrome 浏览器用的就是这个 ...
- JVM从零开始(二) -垃圾回收机制以及内存分代模型
JVM中垃圾回收的判定标准 最终目的是将内存中无用的对象回收掉.具体的判定方法有: 引用计数法,不采用,指的是维护对象被引用的次数,次数为0则意味着是垃圾. 可达性算法-GC Roots tracin ...
- 一文读懂三种并发控制机制(封锁、时间戳、有效性确认,大量例子+证明)
文章目录 并发控制 概述 事务特性 定义 并发控制机制 串行调度和可串行调度 调度 串行调度 可串行化调度 事务和调度的记法 冲突可串行化 冲突 优先图 证明 使用锁的可串行化实现 锁 封锁调度器 两 ...
- 一文读懂RocketMQ的存储机制
一.存储方式 业界主流的 MQ 产品像 RabbitMQ.RocketMQ.ActiveMQ.Kafka 都是支持持久化存储的,而 ZeroMQ 不需要支持持久化存储.业务系统也确实需要 MQ 支持持 ...
- 一文读懂熔断器和重试机制
导语:随着微服务的流行,熔断作为其中一项很重要的技术也广为人知.当微服务的运行质量低于某个临界值时,启动熔断机制,暂停微服务调用一段时间,以保障后端的微服务不会因为持续过负荷而宕机.本文作者介绍了熔断 ...
- V8 —— 你需要知道的垃圾回收机制
前言 V8 blog近日发布了文章描述了"并发标记"的新技术,提升标记过程的效率. 并发标记是一个主要用新的平行和并发的垃圾收集器替换旧的垃圾回收器的项目,现在Chrome 64和 ...
- 垃圾回收只知道标记清除?一文帮你打通V8垃圾回收
前言 本文旨在帮你建议起垃圾回收的体系化知识,仔细品味目录,相信你能体会得的到. V8 垃圾回收核心思路 第一步 通过 GC Root 标记活动对象与非活动对象 如何判断活动对象? V8 通过 可访问 ...
- JS 内存泄漏与垃圾回收机制
前言 不管什么程序语言,内存生命周期基本是一致的: 分配你所需要的内存 使用分配到的内存(读.写) 不需要时将其释放\归还 所有语言 第二部分都是明确的,第一和第三部分在 底层语言 中是明确的.但在像 ...
最新文章
- TCP网络那点破事!三次握手、四次挥手、TIME-WAIT、HTTP 2.0 ....
- 农民丰收节交易英德海奇组委会议-陈业海:功能农业大健康
- js读取div从html中导入,在html中div+css布局的简单应用...-js+div+css下拉导航菜单完整代...-CSS文件的条件导入 - Gene Li_169IT.COM...
- makefile——小试牛刀
- python中和为k的个数_程序查找在python中总计为k的不同组合的数量
- 中文整合包_案例 | 美研市场营销和整合营销专业1620Fall 580+申请实例(含MS+PHD)...
- 华为鸿蒙系统适合机型,华为鸿蒙os2.0系统适用哪些机型
- VB获取Windows操作系统所有版本
- 文本圆角背景_ppt模板航天日PPT,半透明几何圆角长方形文本框
- (详解)----冒泡排序---(图解)
- 数据库练习题归纳整理
- gopher攻击mysql_CTFweb类型(二十七)gopher对mysql的利用及例题讲解
- 教你三步实现CDH到星环TDH的平滑迁移
- 服务器虚拟资源池,大型医院基于Hyper-V的虚拟化服务器资源池构建
- HTTP 和 DNS 原理概念了解 ;
- resource outo区别
- 计算机的基本组成及工作原理(1)
- 基于NRF52832蓝牙芯片的电子价签(电子墨水屏)
- laydate日期控件修改去除秒保留时分
- 借助向 Dev Channel 內部人員提供的最新預覽版本,Microsoft 已將舊版本地管理員密碼解決方案(也稱為 LAPS)直接集成到 Windows 11 中
热门文章
- Matlab论文插图绘制模板第46期—帕累托图(Pareto)
- 如何用极路由+OpenWrt+RTL电视棒搭建一台SDR服务器,并隐秘地捕获和传输数据
- 强劲大小核结构 三星将推八核处理器
- 测试正则表达式的小方法
- 美颜技术---引导滤波 Guided Filter
- sqlserver数据库的使用
- 小熊派BearPi-HM nano开发板 -- MobaXterm使用详情、VScode连接编译主机、小熊派源码获取及烧录
- STM8在STVD下开发所需的中断向量表模版
- 【知识图谱】实践篇——基于知识图谱的《红楼梦》人物关系可视化及问答系统实践:part1项目介绍与环境准备
- Contents mismatch at: 08000000H (Flash=FFH Required=00H) ! Too many errors to display !