iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > html >V8的内存管理与垃圾回收算法是什么
  • 637
分享到

V8的内存管理与垃圾回收算法是什么

2024-04-02 19:04:59 637人浏览 八月长安
摘要

今天小编给大家分享一下V8的内存管理与垃圾回收算法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来

今天小编给大家分享一下V8的内存管理与垃圾回收算法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

V8的内存管理与垃圾回收算法是什么

V8的内存限制与解决办法

V8最初为浏览器设计,遇到大内存使用的场景较少,在设计上默认对内存使用存在限制,只允许使用部分内存,64位系统可允许使用内存约1.4g,32位系统约0.7g。如下代码所示,在node中查看所依赖的V8引擎的内存限制方法:

process.memoryUsage();

// 返回内存的使用量,单位字节
{
  rss: 22953984,
  // 申请的总的堆内存
  heapTotal: 9682944,
  // 已使用的堆内存
  heapUsed: 5290344,
  external: 9388
}

V8的内存管理与垃圾回收算法是什么

V8限制内存使用大小还有另一个重要原因,堆内存过大时V8执行垃圾回收的时间较久(1.5g50ms),做非增量式的垃圾回收要更久(1.5g1s)。在后续讲解了V8的垃圾回收机制后相信大家更能感同身受。

虽然V8引擎对内存使用做了限制,但是同样暴露修改内存限制的方法,就是启动V8引擎时添加相关参数,下面代码演示在Node中修改依赖的V8引擎内存限制:

# 更改老生代的内存限制,单位mb
node --max-old-space-size=2048 index.js

# 更改新生代的内存限制,单位mb
node --max-semi-space-size=1024=64 index.js

这里需要注意的是更改的新生代的内存的语法已经更改为上述的写法,且单位也由kb变成了mb,旧的写法是node --max-new-space-size,可以通过下面命令查询当前Node环境修改新生代内存的语法:

node --v8-options | grep max

V8的内存管理与垃圾回收算法是什么

V8垃圾回收策略

在引擎的垃圾自动回收机制的历史演变中,人们发现是没有一种通用的可以解决任何场景下垃圾回收的算法的。因此现代垃圾回收算法根据对象的存活时间将内存垃圾进行分代分代垃圾回收算法就是对不同类别的内存垃圾实行不同的回收算法。

V8将内存分为新生代老生代两种:

  • 新生代内存中的对象存活时间较短

  • 老生代内存中代对象存活时间较长或是常驻内存

新生代内存存放在新生代内存空间(semispace)中,老生代内存存放在老生代内存空间中(oldspace),如下图所示:

V8的内存管理与垃圾回收算法是什么

  • 新生代内存采用Scavenge算法

  • 老生代内存采用Mark-SweepMark-Compact算法

下面我们看看Scavenge的算法逻辑吧!

Scavenge算法

对于新生代内存的内存回收采用Scavenge算法,Scavenge的具体实现采用的是Cheney算法。Cheney算法是将新生代内存空间一分为二,一个空间处于使用状态(FromSpace),一个空间处于空闲状态(称为ToSpace)。

V8的内存管理与垃圾回收算法是什么

在内存开始分配时,首先在FromSpace中进行分配,垃圾回收机制执行时会检查FromSpace中的存活对象,存活对象会被会被复制到ToSpace,非存活对象所占用的空间将被释放,复制完成后FromSpaceToSpace的角色将翻转。当一个对象多次复制后依然处于存活状态,则认为其是长期存活对象,此时将发生晋升,然后该对象被移动到老生代空间oldSpace中,采用新的算法进行管理。

V8的内存管理与垃圾回收算法是什么

Scavenge算法其实就是在两个空间内来回复制存活对象,是典型的空间换时间做法,所以非常适合新生代内存,因为仅复制存活的对象且新生代内存中存活对象是占少数的。但是有如下几个重要问题需要考虑:

  • 引用避免重复拷贝

假设存在三个对象temp1、temp2、temp3,其中temp2、temp3都引用了temp1,js代码示例如下:

var temp2 = {
  ref: temp1,
}

var temp3 = {
  ref: temp1,
}

var temp1 = {}

FromSpace中拷贝temp2ToSpace中时,发现引用了temp1,便把temp1也拷贝到ToSpace,是一个递归的过程。但是在拷贝temp3时发现也引用了temp1,此时再把temp1拷贝过去则重复了。

要避免重复拷贝,做法是拷贝时给对象添加一个标记visited表示该节点已被访问过,后续通过visited属性判断是否拷贝对象。

  • 拷贝后保持正确的引用关系

还是上述引用关系,由于temp1不需要重复拷贝,temp3被拷贝到ToSpace之后不知道temp1对象在ToSpace中的内存地址。

做法是temp1被拷贝过去后该对象节点上会生成新的field属性指向新的内存空间地址,同时更新到旧内存对象的forwarding属性上,因此temp3就可以通过旧temp1forwarding属性找到在ToSpace中的引用地址了。

内存对象同时存在于新生代和老生代之后,也带来了问题:

  • 内存对象跨代(跨空间)后如何标记

const temp1 = {}

const temp2 = {
  ref: temp1,
}

比如上述代码中的两个对象temp1temp2都存在于新生代,其中temp2引用了temp1。假设在经过GC之后temp2晋升到了老生代,那么在下次GC的标记阶段,如何判断temp1是否是存活对象呢?

在基于可达性分析算法中要知道temp1是否存活,就必须要知道是否有根对象引用引用了temp1对象。如此的话,年轻代的GC就要遍历所有的老生代对象判断是否有根引用对象引用了temp1对象,如此的话分代算法就没有意义了。

解决版本就是维护一个记录所有的跨代引用的记录集,它是写缓冲区的一个列表。只要有老生代中的内存对象指向了新生代内存对象时,就将老生代中该对象的内存引用记录到记录集中。由于这种情况一般发生在对象写的操作,顾称此为写屏障,还一种可能的情况就是发生在晋升时。记录集的维护只要关心对象的写操作和晋升操作即可。此是又带来了另一个问题:

  • 每次写操作时维护记录集的额外开销

优化的手段是在一些Crankshaft操作中是不需要写屏障的,还有就是栈上内存对象的写操作是不需要写屏障的。还有一些,更多的手段就不在这里过多讨论。

  • 缓解Scavenge算法内存利用率不高问题

新生代内存中存活对象占比是相对较小的,因此可以在分配空间时,ToSpace可以分配的小一些。做法是将ToSpace空间分成S0S1两部分,S0用作于ToSpaceS1与原FromSpace合并当成FromSpace

V8的内存管理与垃圾回收算法是什么

Scavenge算法中深度/广度优先的区别

垃圾回收算法中,识别内存对象是否是垃圾的机制一般有两种:引用计数基于可达性分析

基于可达性分析,就是找出所有的根引用(比如全局变量等),遍历所有根引用,递归根引用上的所有引用,凡是被遍历到的都是存活对象并打上标记,此时空间中的其他内存对象都是死对象,由此构建了一个有向图

考虑到递归的限制问题,递归逻辑一般采用非递归实现,常见的有广度优先和深度优先算法。两者的区别在于:

  • 深度优先拷贝到ToSpace时改变了内存对象的排列顺序,使得有引用关系的对象距离较近。原因是拷贝完自己之后直接拷贝自己引用的对象,因此相关的对象便在ToSpace中靠的较近

  • 深度优先正好相反

因为CPU的缓存策略,会在读取内存对象时有很大概率把他后面的对象一起读,目的是为了更快的命中缓存。因为在代码开发期间很常见的场景就是obj1.obj2.obj3,此时CPU读取obj1时如果把后面的obj2obj3一起读的话,则很利于命中缓存。

所以深度优先的算法更利于业务逻辑命中缓存,但是其实现需要依赖额外的栈辅助实现算法,对内存空间有消耗。广度优先则相反,无法提升缓存命中,但是其实现可以利用指针巧妙的避开空间消耗,算法的执行效率高。

新生代内存对象的晋升条件

新生代中的内存对象如果想晋升到老生代需要满足如下几个条件:

  • 对象是否经历过Scavenge回收

  • ToSpace的内存使用占比不能超过限制

判断是否经历过Scavenge的GC的逻辑是,每次GC时给存活对象的age属性+1,当再次GC的时候判断age属性即可。基本的晋升示意图如下所示:

V8的内存管理与垃圾回收算法是什么

老生代内存中,长期存活的对象较多,无法采取Scavenge算法回收的原因在于:

  • 存活对象较多导致复制效率低下

  • 浪费了一半的内存空间

老生代内存对象的回收算法

老生代内存空间的垃圾回收采用的是标记清除Mark-Sweep)和标记整理Mark-Compact)结合的方式。标记清除分为两部分:

  • 标记阶段

  • 清除阶段(如果是标记整理则是整理阶段)

在标记阶段遍历老生代堆内存中的所有内存对象,并对活着的对象做标记,清除阶段只清理未被标记的对象。原因是:老生代内存中非存活对象占少数。

V8的内存管理与垃圾回收算法是什么

如上图所示,标记清除存在的一个问题是清理之后存在了不连续的空间导致无法继续利用,所以对于老生代内存空间的内存清理需要结合标记整理的方案。该方案是在标记过程中将活着的对象往一侧移动,移动完成后再清理界外的所有非存活对象移除。

V8的内存管理与垃圾回收算法是什么

垃圾回收的全暂停

垃圾回收时需要暂停应用执行逻辑,待垃圾回收机制结束后再恢复应用执行逻辑,该行为称为“全暂停”,也就是常说的Stop The World,简称STW。对新生代内存的垃圾回收该行为对应用执行影响不大,但是老生代内存由于存活对象较多,所以老生代内存的垃圾回收造成的全停顿影响非常大。

V8的内存管理与垃圾回收算法是什么

V8为了优化GC的全暂停时间,还引入了增量标记并发标记并行标记增量整理并行清理延迟清理等方式。

STW优化

衡量垃圾回收所用时间的一个重要指标是执行 GC 时主线程暂停的时间量。STW所带来的影响是无法接受的,因此V8也采取的很多优化手段。

  • 并行GC

GC的过程需要做大量的事情从而在主线程上导致STW现象,并行GC的做法是开多个辅助线程分担GC的事情。该做法依然无法避免STW现象的,但是可以减少STW的总时间,取决于开启的辅助线程数量。

V8的内存管理与垃圾回收算法是什么

  • 增量GC

增量GC将GC工作进行拆分,并在主线程中间歇的分步执行。该做法并不会减少GC的时间,相反会稍微花销,但是它同样会减少GC的STW的总时间。

V8的内存管理与垃圾回收算法是什么

  • 并发GC

并发GC是指GC在后台运行,不再在主线程运行。该做法会避免STW现象。

V8的内存管理与垃圾回收算法是什么

  • 空闲时间GC

Chrome中动画的渲染大约是60帧(每帧约16ms),如果当前渲染所花费时间每达到16.6ms,此时则有空闲时间做其他事情,比如部分GC任务。

V8的内存管理与垃圾回收算法是什么

减少垃圾回收的影响

想要提高执行效率要尽量减少垃圾回收的执行和消耗:

  • 慎把内存当作缓存,小心把对象当作缓存,要合理限制过期时间和无限增长的问题,可以采用lru策略

  • Node中避免使用内存存储用户会话,否则在内存中存放大量用户会话对象导致老生代内存激增,影响清理性能进而影响应用执行性能和内存溢出。改进方式使用使用Redis等。将缓存转移到外部的好处:

    • 减少常驻内存对象的数量,垃圾回收更高效

    • 进程之间可以共享缓存

以上就是“V8的内存管理与垃圾回收算法是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网html频道。

--结束END--

本文标题: V8的内存管理与垃圾回收算法是什么

本文链接: https://www.lsjlt.com/news/97567.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • V8的内存管理与垃圾回收算法是什么
    今天小编给大家分享一下V8的内存管理与垃圾回收算法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来...
    99+
    2024-04-02
  • 分析Java内存管理与垃圾回收
    这篇文章主要介绍“分析Java内存管理与垃圾回收”,在日常操作中,相信很多人在分析Java内存管理与垃圾回收问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分析Java内存管理...
    99+
    2024-04-02
  • PHP 垃圾回收机制与内存管理
    php 的内存管理使用垃圾回收机制,它会在运行时自动释放不再使用的内存,基于引用计数原理运作。为了避免内存泄漏,遵循以下最佳实践:销毁不再需要的变量、避免循环引用、使用弱引用。 PHP...
    99+
    2024-05-03
    php 垃圾回收
  • C++ 内存管理中的自动垃圾回收
    c++++ 中自动垃圾回收需要使用第三方工具或库。可以使用智能指针或垃圾回收器库。智能指针自动释放底层对象,而垃圾回收器库使用算法跟踪不再使用的数据结构。案例:使用智能指针 std::s...
    99+
    2024-05-04
    c++ 垃圾回收 垃圾回收器 标准库
  • Python的内存管理和垃圾回收机制
    本篇内容介绍了“Python的内存管理和垃圾回收机制”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!对象的内存使用赋值语句是语言最常见的功能了...
    99+
    2023-06-02
  • 详解php内存管理机制与垃圾回收机制
    目录一、内存管理机制二、垃圾回收机制一、内存管理机制 先看一段代码: <?php //内存管理机制 var_dump(memory_get_usage());//获...
    99+
    2024-04-02
  • JVM教程之内存管理和垃圾回收(三)
    JVM内存组成结构JVM栈由堆、栈、本地方法栈、方法区等部分组成,结构图如下所示:1)堆所有通过new创建的对象的内存都在堆中分配,其大小可以通过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survi...
    99+
    2023-05-31
    jvm 内存管理 垃圾回收
  • web前端中V8的垃圾回收和内存限制如何理解
    这篇文章将为大家详细讲解有关web前端中V8的垃圾回收和内存限制如何理解,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前言在第三次浏览器大战中,来自Google的Chrome浏览器凭借优异的...
    99+
    2023-06-04
  • 深入剖析Go语言中的垃圾回收与内存管理
    在Go语言中,垃圾回收(Garbage Collection,简称GC)是自动进行的,开发者不需要手动管理内存。Go语言的GC使用的...
    99+
    2023-10-12
    Go语言
  • php内存管理机制与垃圾回收机制的示例分析
    这篇文章给大家分享的是有关php内存管理机制与垃圾回收机制的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、内存管理机制先看一段代码:<php//内存管理机制var_dump(memory_get...
    99+
    2023-06-15
  • 如何利用Go语言的垃圾回收器管理内存
    Go语言的垃圾回收器是自动管理内存的,开发者不需要手动释放内存。下面是一些使用Go语言垃圾回收器的最佳实践:1. 避免手动分配内存:...
    99+
    2023-10-08
    Golang
  • 怎么进行Java内存与垃圾回收调优
    本篇文章给大家分享的是有关怎么进行Java内存与垃圾回收调优,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。要了解Java垃圾收集机制,先理解JVM内存模式是非常重要的。今天我们...
    99+
    2023-06-17
  • PHP垃圾回收及内存管理相关内容有哪些
    这篇文章主要讲解了“PHP垃圾回收及内存管理相关内容有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP垃圾回收及内存管理相关内容有哪些”吧!PHP 垃圾回收与内存管理指引本文将要讲述...
    99+
    2023-06-21
  • Kubernetes中的垃圾回收方法是什么
    本篇内容介绍了“Kubernetes中的垃圾回收方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!考...
    99+
    2024-04-02
  • Go语言内存管理和垃圾回收的最佳实践
    Go语言在内存管理和垃圾回收方面有一些最佳实践,可以帮助开发人员有效地管理内存和减少垃圾回收的影响。以下是一些常见的最佳实践:1. ...
    99+
    2023-10-08
    Golang
  • 探索Go语言中的内存优化技术与垃圾回收器管理
    Go语言中的内存优化技术和垃圾回收器管理是为了提高程序性能和减少内存占用。1. 栈分配:Go语言使用栈进行变量的分配,栈上的内存分配...
    99+
    2023-10-08
    Golang
  • jvm垃圾回收机制的原理是什么
    JVM(Java虚拟机)的垃圾回收机制是自动管理内存的一种机制,它通过识别和释放不再被程序使用的对象,以防止内存泄漏和内存溢出等问题...
    99+
    2023-09-25
    jvm
  • Java垃圾回收机制的原理是什么
    本篇内容主要讲解“Java垃圾回收机制的原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java垃圾回收机制的原理是什么”吧!Java 垃圾回收机制1. 垃圾回收主要关注 Java 堆图...
    99+
    2023-06-15
  • JVM垃圾回收基本原理是什么
    这篇文章主要介绍“JVM垃圾回收基本原理是什么”,在日常操作中,相信很多人在JVM垃圾回收基本原理是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JVM垃圾回收基本原理是什么”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-02
  • Java垃圾回收调优的方法是什么
    这篇文章主要讲解了“Java垃圾回收调优的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java垃圾回收调优的方法是什么”吧!性能调优目标要是可确定且可测量的,这非常重要。这些目标...
    99+
    2023-06-17
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作