V8 内存管理和垃圾回收机制总结

这篇文章主要介绍 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内存控制

完。

原文地址:https://www.cnblogs.com/ysk123/p/11656312.html

时间: 2024-08-06 16:06:40

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

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

http://backend.blog.163.com/blog/static/20229412620128233285220/ 内存管理和垃圾回收机制是JVM最核心的两个组成部分,对其内部实现的掌握是Java开发人员开发出高质量的Java系统的必备条件.最近整理了一些关于JVM内存管理和垃圾回收方面的知识,这里梳理一下,分享给大家,希望能够对Java虚拟机有更深入的了解. 1. JVM内存管理 首先,JVM将内存组织为主内存和工作内存两个部分.主内存中主要包括本地方法区和堆.每个线程都有一个工

详解JVM内存管理与垃圾回收机制 (上)

Java应用程序是运行在JVM上的,得益于JVM的内存管理和垃圾收集机制,开发人员的效率得到了显著提升,也不容易出现内存溢出和泄漏问题.但正是因为开发人员把内存的控制权交给了JVM,一旦出现内存方面的问题,如果不了解JVM的工作原理,将很难排查错误.本文将从理论角度介绍虚拟机的内存管理和垃圾回收机制,算是入门级的文章,希望对大家的日常开发有所助益. 一.内存管理 也许大家都有过这样的经历,在启动时通过-Xmx或者-XX:MaxPermSize这样的参数来显式的设置应用的堆(Heap)和永久代(P

.Net程序的内存管理和垃圾回收机制

.NET 内存管理和垃圾回收 C/C++ 程序需要开发者手动分配和释放内存,.Net程序则使用垃圾回收技术自动收集不再使用的内存.垃圾回收器(GC)使用引用 跟踪占用内存的对象,如果对象被设置为null或已不在使用范围,GC就会标志该对象为可回收,这样GC就可以回收被这些对象占用的内存. 垃圾回收器(GC)使用Win32? VirtualAlloc() 接口为自己的堆分配内存,.Net托管堆是一个巨大连续的虚拟内存.GC先预留虚拟内存,当托管堆增长时则提交内存.GC跟踪托管堆末尾可用的地址并把下

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

一.JVM的生命周期 JVM实例:一个独立运行的java程序,是进程级别 JVM执行引擎:用户运行程序的线程,是JVM实例的一部分 JVM实例的诞生 当启动一个java程序时.一个JVM实例就诞生了,任何一个拥有public static void main(string[] args)的函数都可以作为实例的运行启点 2.  JVM实例运行 main作为程序初始化线程的起点,任何其他线程由其启动. JVM有两种线程:守护线程和非守护线程.守护线程由JVM使用.main启动后将是非守护线程. 3.

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

一.python内存申请: 1.python的内存管理分为六层:最底的两层有OS控制.第三层是调用C的malloc和free等进行内存控制.第四层第五层是python的内存池.最上层使我们接触的直接对python对象进行操作. 2.python申请对象时候小于256Byte的字节申请回直接使用python自己的内存分配系统,当大于256Byte的时候会调用malloc直接分配一个256k的大内存空间.释放内存空间时候会回收到内存池中而不是直接调用free释放掉. 3.深浅拷贝的不同(id?内存地

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

PHP5的内存管理 对象传递 PHP5使用了Zend引擎II,对象被储存于独立的结构Object Store中,而不像其它一般变量那样储存于Zval中(在PHP4中对象和一般变量一样存储于Zval).在Zval中仅存储对象的指针而不是内容(value).当我们复制一个对象或者将一个对象当作参数传递给一个函数时,我们不需要复制数据.仅仅保持相同的对象指针并由另一个zval通知现在这个特定的对象指向的Object Store.由于对象本身位于Object Store,我们对它所作的任何改变将影响到所

JAVA内存管理和垃圾回收机制

JVM内存组成结构 JVM栈由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)堆 所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制.堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由From Space和To Space组成,结构图如下所示: 新生代.新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小可以由-Xmn来控制,也可以用-XX:Surv

java虚拟机——内存管理与垃圾回收机制

一  java内存区域与内存溢出异常(OOM) 1.运行时数据区域划分  

Java内存管理及垃圾回收总结

概述 Java和C++的一个很重要的差别在于对内存的管理.Java的自己主动内存管理及垃圾回收技术使得Java程序猿不须要释放废弃对象的内存.从而简化了编程的过程.同一时候也避免了因程序猿的疏漏而导致的内存泄露问题. 内存管理和垃圾回收是JVM很重要的一个部分.深入理解Java的内存管理和垃圾回收机制是避免及修复Java相关异常(OutOfMemoryError, StackOverflowError),理解Java对象创建过程,有效利用内存.构建高性能Java应用的前提.本文将先后介绍Java