这篇文章主要介绍 V8 的内存管理和垃圾回收知识。

V8 内存管理及垃圾回收机制浅析

由于 V8 引擎的原因,Node 在操作大内存对象时受到了一些限制,在 64 位的机器上,默认最大操作的对象大小约为 1.4G,在 32 位的机器上,默认最大操作的对象大小约为 0.7G。

如果我们的 Node 程序会经常操作一些大内存的对象,可以对这个默认值进行修改:

node --max-old-space-size=1700 index.js
node --max-new-space-size=1024 index.js

其中,max-old-space-size 表示设置老生代内存空间的最大容量,max-new-space-size 表示这只新生代内存空间的最大容量。但这两个值也是有上限的,不能无限设置,其中老生代内存空间最大的值约为 1.7G,新生代最大内存空间约为 1.0G。

至于新生代和老生代,这是 V8 对内存的一个分类,后文再介绍。

回到操作大内存对象的问题,如果 1.7G 的内存还是不够大怎么办呢?要知道 1.7G 是在 V8 引擎层面上做出的限制,要想避开这种限制,我们可以使用 Buffer 对象,Buffer 对象的内存分配在 C++ 层面进行,不受 V8 引擎限制。

注:通过 process.memoryUsage() 方法可以用来查看 V8 引擎的内存使用量,通过 os.totalmem() 方法和 os.freemem() 方法分别可以查看操作系统的总内存和空闲内存。

// 查看 V8 的内存使用情况
process.memoryUsage()
{
rss: 31469568,
heapTotal: 7708672,
heapUsed: 5152856,
external: 8609
} // 查看操作系统总内存
os.totalmem()
8279511040
// 查看操作系统的空闲内存
os.freemem()
1610977280

通过上面几个方法获取到的内存都是以字节为单位。

新生代和老生代

V8 将内存分为两类:新生代内存空间和老生代内存空间,新生代内存空间主要用来存放存活时间较短的对象,老生代内存空间主要用来存放存活时间较长的对象。对于垃圾回收,新生代和老生代有各自不同的策略,下面依次进行介绍。

新生代垃圾回收

新生代内存中的垃圾回收主要通过 Scavenge 算法进行,具体实现时主要采用了 Cheney 算法。Cheney 将内存空间一分为二,每部分都叫做一个 Semispace,这两个 Semispace 一个处于使用,一个处于闲置。处于使用中的 Semispace 也叫作 From,处于闲置中的 Semispace 也叫作 To。

在垃圾回收运行时时,会检查 From 中的对象,当某个对象需要被回收时,将其留在 From 空间,剩下的对象移动到 To 空间,然后进行反转,将 From 空间和 To 空间互换。进行垃圾回收时,会将 To 空间的内存进行释放,如下图所示:

新生代垃圾回收.png

简而言之,就是 From 空间中存放不需要被回收的对象,To 空间中存放需要被回收的对象,当垃圾回收运行时,将 To 空间中的对象全部进行回收。

新生代对象的晋升

前面说过,新生代内存空间用来存放存活时间较短的对象,老生代内存空间用来存放存活时间较长的对象。新生代中的对象可以晋升到老生代中,具体有两种方式:

  1. 在垃圾回收的过程中,如果发现某个对象之前被清理过,那么会将其晋升到老生代内存空间中
  2. 在 From 空间和 To 空间进行反转的过程中,如果 To 空间中的使用量已经超过了 25%,那么就将 From 中的对象直接晋升到老生代内存空间中

老生代垃圾回收

说完新生代的垃圾回收,再来看下老生代中的垃圾回收。首先,老生代内存空间和新生代内存空间的结构不一样,其是一个连续的结构,而不像新生代内存空间那样分为 From 和 To 两个部分:

老生代内存空间.png

老生代内存空间中的垃圾回收有标记清除(Mark Sweep)和标记合并(Mark Compact)两种方式。

Mark Sweep

Mark Sweep 是将需要被回收的对象进行标记,在垃圾回收运行时直接释放相应的地址空间,如下图所示(红色的内存区域表示需要被回收的区域):

标记清除.png

如上图所示,使用 Mark Sweep 进行垃圾回收会产生一个问题,就是垃圾回收后内存会出现不连续的情况,为了解决这个问题,出现了 Mark Compact 方案。

Mark Compact

Mark Compact 的思想有点像新生代垃圾回收时采取的 Cheney 算法:将存活的对象移动到一边,将需要被回收的对象移动到另一边,然后对需要被回收的对象区域进行整体的垃圾回收。

标记合并.png

上图展示了在老生代内存空间使用 Mark Compact 进行垃圾回收的过程。

总结

本文主要简单介绍了 Node 的内存管理和垃圾回收相关的知识:

  • V8 的大对象操作限制问题和解决方案
  • 获取内存使用量的几个方法
  • 新生代和老生代的概念
  • 新生代和老生代的垃圾回收方案

附:参考资料

V8的垃圾回收机制与内存限制

node 内存限制的问题

node内存控制

完。

V8 内存管理和垃圾回收机制总结的更多相关文章

  1. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  2. JVM内存管理和垃圾回收机制介绍

    http://backend.blog.163.com/blog/static/20229412620128233285220/     内存管理和垃圾回收机制是JVM最核心的两个组成部分,对其内部实 ...

  3. JVM的生命周期、体系结构、内存管理和垃圾回收机制

    一.JVM的生命周期 JVM实例:一个独立运行的java程序,是进程级别 JVM执行引擎:用户运行程序的线程,是JVM实例的一部分 JVM实例的诞生 当启动一个java程序时.一个JVM实例就诞生了, ...

  4. java基础(一):谈谈java内存管理与垃圾回收机制

    看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...

  5. JavaScript 执行环境、作用域、内存管理及垃圾回收机制

    前言 JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. [原理]找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔( ...

  6. python的内存管理与垃圾回收机制学习

    一.python内存申请: 1.python的内存管理分为六层:最底的两层有OS控制.第三层是调用C的malloc和free等进行内存控制.第四层第五层是python的内存池.最上层使我们接触的直接对 ...

  7. 【第1题】 Pythonn内存管理以及垃圾回收机制

    内存管理 Python解释器由c语言开发完成,py中所有的操作最终都由底层的c语言来实现并完成,所以想要了解底层内存管理需要结合python源码来进行解释. 1. 两个重要的结构体 include/o ...

  8. PHP 内存管理及垃圾回收机制

    PHP5的内存管理 对象传递 PHP5使用了Zend引擎II,对象被储存于独立的结构Object Store中,而不像其它一般变量那样储存于Zval中(在PHP4中对象和一般变量一样存储于Zval). ...

  9. Python的内存管理和垃圾回收机制

    内存管理 Python解释器由c语言开发完成,py中所有的操作最终都由底层的c语言来实现并完成,所以想要了解底层内存管理需要结合python源码来进行解释. 1. 两个重要的结构体 include/o ...

随机推荐

  1. 关于 base64 编码

    一.什么是Base64编码 Base64是一种用64个字符来表示任意二进制数据的方法.它是一种编码方式,而非加密方式.它通过将二进制数据转变为64个"可打印字符",完成了数据在HT ...

  2. .net core的Swagger接口文档使用教程(一):Swashbuckle

    现在的开发大部分都是前后端分离的模式了,后端提供接口,前端调用接口.后端提供了接口,需要对接口进行测试,之前都是使用浏览器开发者工具,或者写单元测试,再或者直接使用Postman,但是现在这些都已经o ...

  3. CSS基础 结构伪类选择器 last-child、first-child和nth-of-type的使用方法

    一.通过伪类选择器查找单个标签元素html结构 <div> <a herf='#'>导航1</a> <a herf='#'>导航2</a> ...

  4. From Hero to Zero

    题目描述: 有一天,小明给了你两个数字n和k,现在,你需要对数字n进行一下操作: 对于每一步操作,你可以选择下面其中一个项目: 1.将n的值减少1. 2.如果n能被k整除,可以使n/k 比如:n=27 ...

  5. update sql时,常记错同时更新多个参数用and,正确是用逗号

    记录一下,经常记错的一个点,在update多个参数时,多个参数之间用and连接,这个时候,语句就会报错了 其实,正确的是用逗号隔开, 使用SQL中的update更新多个字段值,set后面的条件要用逗号 ...

  6. c# - 常量定义与赋值

    1.前言 c#与Java很相似,但是不一样,又与js(JavaScript)相似,但是也不一样,所以我认为c#是Java和 js的孩子. 2.常量定义 字符串: const string = &quo ...

  7. zabbix监控图形中文乱码的解决方法

    问题描述: 最近搭建了一套zabbix,当我把语言切换到中文的时候,发现监控的图形界面中一些中文参数乱码,但是图形界面在英文环境下完全没有乱码问题.如下图(中文界面): 解决方法: 解决方法有两种,方 ...

  8. centos7 安装zabbix3.0 安装zabbix4.0 yum安装zabbix 国内源安装zabbix 阿里云服务器安装zabbix

    首先,此篇文章是有原因的. 刚开始也和大家一样来学习安装zabbix 奈何网上的教程和现实出现不一样的情况 在安装zabbix过程中,因为zabbix下载源是在国外,下载途中会出现终止下载的情况 tr ...

  9. kibana7.x安装配置操作elasticsearch

    什么是Kibana? Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等. 而且还 ...

  10. ELF文件格式学习总结

    ELF文件格式学习总结 ELF文件格式学习总结1. 概述2. 目标文件结构3. ELF文件头3.1 魔数3.2 文件类型3.3 机器类型4. ELF文件内容4.1段表4.2字符串表(.**strtab ...