1.V8引擎和垃圾处理机制

1.1、v8

1.1.1、V8的内存限制

一般后端语言中,基本的内存使用上没有什么限制**,然后node中通过js使用内存会发现,只能使用部分内存,64位系统约1.4GB, 32位系统约0.7GB。**如果我们读入内存一个2GB的文件,即使物理内存有32GB,但在这样单个Node进程的情况下,计算机的内存资源无法得到充足使用。

造成这个问题的原因是什么?

主要因为Node基于V8构建,所以Node中使用js对象基本上都是V8自己的方式进行分配和管理,V8的内存管理机制在浏览器场景下使用绰绰有余,但在Node中限制了开发者随心所欲使用大内存的想法。

1.1.2、V8的对象分配

V8中,对象都是通过堆来分配的,我们可以通过process.memoryUsage()来查看内存的使用情况。该函数返回值中heapTpal是申请到的堆内存,heapUsed是当前使用量。当我们声明变量并赋值的时候,所使用对象就在堆内存中。如果堆的空闲空间不足以分配给新对象,会继续申请堆内存,直到堆的大小超过V8的限制。

为何限制堆内存的大小?

  1. 因为对于网页来说V8的限制值已经绰绰有余
  2. 根本原因是垃圾回收机制的限制。(官方说法1.5GB的垃圾回收堆内存,V8需要50ms以上,做一次非增量式的垃圾回收甚至需要1s以上)。而垃圾回收会引起JS线程暂停执行,在这样时间花销下,应用的性能和响应能力都会下降,这样后端和前端都无法接受

如何内存的限制?

以下两个最大值需要在启动时就指定

  1. 使用命令node --max-old-space-size=1700 test.js //单位为MB 老生代的内存空间
  2. node --max-new-space-size=1700 test.js//单位KB 新生代的内存空间

1.2、垃圾回收机制

1.2.1、内存分代

人们发现没有任何垃圾回收算法能够胜任所有场景(对象生存周期的长短不一),不同的算法只能针对特定的情况具有最好的效果。因此现代的垃圾回收算法中按照对象的存活时间将内存的垃圾回收进行不同的分代(新生代和老生代),然后分别对不同分代的内存施以更高效的算法,新生代的对象为存活时间较短的对象,老生代的对象为存活时间较长或常驻内存的对象。V8堆的整体大小就是新生代+老生代的内存空间

1.2.1.1、新生代内存

新生代内存由两个reserved_semispace_size所构成,按机器位数在64为上reserved_semispace_size的值为16MB,32位的是8MB。所以新生代内存空间最大值在64位系统和32位系统上分别位32MB和16MB

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v9dS8FAN-1660181620949)(笔记依赖图/image-20220810184031455.png)]

从该图片我们可以得知,V8最大保留空间是4*reserved_semispace_size_+max_old_gendration_size_

1.2.2、scavenge算法-针对于新生代

在Scavenge具体实现中,主要采用了Cheney算法,Cheney算法采用一种复制方式实现垃圾回收算法,

Cheney算法原理

  1. 划分空间,将堆内存一分为二,每一部分空间成为semispace,在这两个semispace空间中,只有一个处于使用中,另一个处于闲置状态,使用状态的semispace空间成为From空间,处于限制状态的空间成为To空间。
  2. 赋值,当我们分配对象时,先在From空间进行分配。当开始进行垃圾回收时,会检查From空间中存活的对象,将存活的对象复制到To空间中,而非存活对象占用的空间将被释放。
  3. 完成复制后,From空间和To空间角色发对换。简而言之,就是垃圾回收过程中,通过将存活对象在两个semispace空间之间进行复制。

Scavenge算法的缺点

  1. 只能使用内存的一半,典型的空间换时间,但由于scavenge由于只赋值存活对象,并且对于生命周期短的场景存活对象只占少部分,因此时间效率比较高
  2. 空间换时间的这种算法,无法大规模应用到所有垃圾回收中,因此scavene只适合在新生代中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BlzUQEdV-1660181620950)(笔记依赖图/image-20220811084318568.png)]

晋升机制

当一个对象经过多次复制依然存活时,它将会被认为是生命周期较长的对象。这种对象随后会被移动到老生代总,采用新的算法进行管理。

晋升条件

  1. 是否经历过Scavenge回收

    • 对象从From空间到To空间时,就会检查它的内存地址来判断该对象是否经历过一次Scavenge回收,如果已经经历过了,会将该对象从From空间复制到老生代空间中,如果没有就复制到To空间中。
  2. To空间内存占用比超过限制
    • 当从From空间到To空间时,如果To空间使用已经超过了25%,则该对象直接晋升到老生代空间中。
    • 设置25%限制原因:因为Scavenge回收完成后,这个To空间会变成From空间,接下来内存会在该空间进行分配,如果占比过高,会影响后续内存分配

1.2.3、Mark-Sweep & Mark-Compact-针对于老生代

老生代不采用Scavenge算法原因

  1. 老生代中存活对象占比大,因此复制存活对象效率低。
  2. 浪费一半空间

Mark-Sweep标记清除

Mark-Sweep在标记阶段遍历堆中所有对象,并标记存活对象,在随后清除阶段中,只清除没有被标记的对象。**因为在老生代中死对象占据较小一部分,而Mark-Sweep只清除死亡对象,就像Scavenge算法,新生代中存活对象占小部分,其算法只处理存活对象,**这样效率就有了提升。

Mark-Sweep算法的缺点

该算法最大问题在于进行一次标记清除回收后**,内存空间会出现不连续的情况**。这种内存碎片会对后续的内存分配造成问题。因为很可能出现需要分配一个大对象的情况,而碎片空间无法完成分配,就会提前触发垃圾回收,而这次回收是不必要的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KfKN3ngS-1660181620950)(笔记依赖图/image-20220811090125259.png)]

Mark-Compact弥补Mark-Sweep碎片空间缺点

Mark-Compact是标记整理,该算法将存活对象往一端进行移动,移动完成后,直接清理掉最右边存活对象后面的内存区域完成回收

缺点:速度慢-需要整理对象

优点:空间开销少

1.2.4、Incremental Marking-针对垃圾回收引起全停顿

为了避免JS应用逻辑和垃圾回收期看到的不一致,垃圾回收的3中基本算法都需要将逻辑暂停下来,等垃圾回收完成后再继续执行,这种行为被称为全停顿在V8分代式垃圾回收中,一次小垃圾回收只收集新生代,由于新生代默认配置小,存活对象少,因此即使是全停顿也影响不大,而对于老生代通常配置大,存活对象多,全堆垃圾回收的标记、清理、整理等动作造成的停顿会比较可怕。

V8为了降低全堆垃圾回收带来的停顿时间,先从标记阶段入手将原本一口气停顿完成的动作改为增量标记,拆分许多小“步进”,每做完一“步进”就让JS应用逻辑执行一小会儿,垃圾回收和JS逻辑交替执行,直到标记阶段完成,V8经过标记改进后,垃圾回收的最大停顿时间减少到了原本的1/6.

V8后续还引进了延迟清理Lazy-Sweeping和增量式整理incremental Compaction,让清理与整理动作也变成增量式,同时还计划引入并行标记和并行清理,进一步利用多核性能降低每次停顿时间。

圾回收的最大停顿时间减少到了原本的1/6.

V8后续还引进了延迟清理Lazy-Sweeping和增量式整理incremental Compaction,让清理与整理动作也变成增量式,同时还计划引入并行标记和并行清理,进一步利用多核性能降低每次停顿时间。

V8引擎和JS垃圾回收机制的详解相关推荐

  1. 浅谈V8引擎中的垃圾回收机制

    浅谈V8引擎中的垃圾回收机制 这篇文章的所有内容均来自 朴灵的<深入浅出Node.js>及A tour of V8:Garbage Collection,后者还有中文翻译版V8 之旅: 垃 ...

  2. Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略

    V8 实现了准确式 GC,GC 算法采用了分代式垃圾回收机制.因此,V8 将内存(堆)分为新生代和老生代两部分. 一.前言 V8的垃圾回收机制:JavaScript使用垃圾回收机制来自动管理内存.垃圾 ...

  3. Java Garbage Collection基础详解------Java 垃圾回收机制技术详解

    最近还是在找工作,在面试某移动互联网公司之前认为自己对Java的GC机制已经相当了解,其他面试官问的时候也不存在问题,直到那天该公司一个做搜索的面试官问了我GC的问题,具体就是:老年代使用的是哪中垃圾 ...

  4. JVM垃圾回收机制GC详解

    作为 Java 语言最重要的特性之一的自动垃圾回收机制,也是基于 JVM 实现的.那么,自动垃圾回收机制到底是如何实现的呢? 1.GC是干啥的? 进行资源的回收 1.1.对于 C/C++ 而言 对于C ...

  5. C#.Net 垃圾回收机制GC详解

    [优点] 1.提高软件系统的内聚. 2.降低编程复杂度,使程序员不必分散精力去处理析构. 3.不妨碍设计师进行系统抽象. 4.减少由于内存运用不当产生的Bug. 5.成功的将内存管理工作从程序的编写时 ...

  6. 前端面试常考题:JS垃圾回收机制

    摘要:众所周知,应用程序在运行过程中需要占用一定的内存空间,且在运行过后就必须将不再用到的内存释放掉,否则就会出现下图中内存的占用持续升高的情况,一方面会影响程序的运行速度,另一方面严重的话则会导致整 ...

  7. js垃圾回收机制(Gc)

    js垃圾收机制(Gc) 1.GC(garbage collection):js具有自动垃圾回收机制,即执行环境会负责管理代码执行过程中使用的内存, 2.GC会定期(周期性)找出那些不再继续使用的变量, ...

  8. js垃圾回收机制,内存泄露和内存溢出,解决闭包产生的内存泄露详解

    一.内存的周期和回收机制 分配内存----->使用内存----->释放内存 1.JS 环境中分配的内存有如下声明周期: 内存分配:当我们声明变量.函数.对象的时候,系统会自动为他们分配内存 ...

  9. 从闭包函数的变量自增的角度 - 解析js垃圾回收机制

    GitHub 前言 感觉每一道都可以深入研究下去,单独写一篇文章,包括不限于闭包,原型链,从url输入到页面展示过程,页面优化,react和vue的价值等等. 代码实现 const times = ( ...

最新文章

  1. Win10系列:VC++调用自定义组件1
  2. VMware 虚拟化编程(7) — VixDiskLib 虚拟磁盘库详解之三
  3. wireshark读写pcap文件_PCAP-file-analysis 利用wireshark捕获tcp ip数据包和pcap文件分析 - 下载 - 搜珍网...
  4. 11:数值的整数次方
  5. pytorch手动实现梯度下降法,随机梯度法--基于logistic Regression并探索Mini batch作用
  6. html让元素纵向排列,html – 如何使元素排列到父元素的外边缘
  7. http --- HTTPS是在安全的传输层上发送的HTTP
  8. 【Python】万花筒
  9. 端午小长假全国接待游客4880万人次,客流同比恢复5成
  10. 递归转手动管理栈的非递归
  11. XSS-Game level 5
  12. Git学习05 --分支管理02
  13. 微信支付java后台
  14. C++对二进制文件的操作实例
  15. linux内存管理方式,简要概括Linux内存管理的方式
  16. 已知两点坐标和三边长度,求三角形第三点的坐标
  17. java异或_干货:Java异或运算符的使用方法
  18. 图像识别中的边框回归笔记,终于搞明白了啊!
  19. python多线程模块threading学习笔记(5)之锁Lock
  20. [DirectX 9.0笔记]第二章 渲染管线

热门文章

  1. 突发!Google 下架拼多多,称存在恶意软件
  2. 三毛最伤心的一百句话
  3. 仪器测量色差和人眼目视不一样
  4. 苹果5概念机_iPhone13概念图:圆形机身环绕镜头,好似手术灯
  5. 偏最小二乘(pls)回归分析 matlab
  6. Java岗的网易/华为/美团/滴滴社招面试经历
  7. 敬回忆一杯酒,来祭奠我那逝去的青春。
  8. FlyAI实验室使用教程【完整版】
  9. Javascript 内存(三):内存泄漏常见场景及分析
  10. vue跳转页面常用的几种方法