V8引擎垃圾回收机制分析

      关于垃圾回收机制是一个比较引人深思的问题,因为常规的业务开发基本是用不到的。但是,又是前端必须了解的一个内容。首先,垃圾回收是跟语言本身的特性有关的。这句话的意思是JS、java等有自己垃圾回收机制存在,不需要开发者手动去进行内存的分配和内存的释放。而C是需要开发者自己去申请内存、释放内存的。下面进入正题:

       1.js的垃圾收集以及其优缺点?
         js使用自动的内存管理,被称为垃圾回收机制。优点是:简化开发、节省代码(不需要像C语言一样手动分配内存,手动释放内存)。缺点:无法完整的掌握内存的分配与回收的具体过程(因为都是系统本身在做,开发者无法全面掌控)

       2.NodeJS中的内存为何重要?
         js网页端的内存泄露如果很小的话,相对不是那么严重,因为影响的单个的用户,每个用户的应用程序独立。但是,对于Node服务进程来说,内存占比过高轻,不再使用的内存也不能即使的释放导致内存占用越来越高,那么轻则影响系统的性能,重则导致进程奔溃。而所谓的内存泄露的意思是指不在使用的内存没有及时释放就叫做内存泄露。

       3.v8的内存限制是多少?如何理解?
          在64位操作系统中可以使用1.4G内存,在32位操作系统中则可以使用0.7G内存。(这里是默认值,有方法突破这个限制)
          js对象是通过V8进行分配管理内存的。node中如何查看内存占比呢?
          console.log(process.memoryUsage());(此代码需要在node中运行)
          {
              rss: 19398656,    // 所有内存占用,包括指令区和堆栈 。这里大概18.5M
              heapTotal: 6504448,    // 堆占用的内存,包含在使用中和空闲的  大概6.5M
              heapUsed: 3696168,    // 用到的堆内存的部分,判断泄露与否以此字段为准  大概3.5M
              external: 8272              // v8引擎内部c++对象占用的内存   大概0.007M
          }
          下图就是他们之间的关系

          

          4.v8的堆内存图解
            

           5.为什么V8有64位1.4G,32位0.7G的内存限制呢?(操作系统不同下面默认为同意操作系统)
              因为V8的垃圾收集工作原理,1.4G(0.7G)的内存完全一次垃圾收集需要1S以上,越大需要的事件也就越大,而每次进行垃圾回收,会停止服务的提供直到垃圾回收完毕。这个暂停的时间叫 Stop The World 这段时间内应用的性能和响应能力会下降。所以,并不是内存越大就是越好的。

           6.V8的垃圾回收机制?
              首先,V8基于分代的垃圾回收机制。不同的代垃圾回收机制是不一样的,按存活的时间来分为新生代和老生代。新生代有form和to两部分组成。
              默认情况下64位: 新生代内存32M,form区域和to区域各占比16M。老生代占比1400M。
                                32位: 新生代内存16M,form区域到to区域各占比8M。老生代占比700M。
             

              新生代的垃圾回收:
                   1.检查form区域的存活对象,如果存活则拷贝到to区域,然后清除整个from区域释放内存。存活的标准就是引用计数。
                   2.互换form区域跟to区域再次进行上述的阶段死循环执行。
                   3.存活的标准采用引用计数的形式。
                   4.新生代的空间小,存活对象少,扫描存活数据采用广度优先的扫描策略。
                   5.当一个对象经历多次空间互换都存在,年纪从0开始,每次拷贝互换对象年纪加1,当年纪到达5的时候默认其为长期存活移入老生代中。或者新的数据太大,新生代放不下的时候会直接将数据移动至老生代中。

               那么什么是引用计数呢?很简单,就是当前的对象被引用的次数会记录在一张引用次数表中,如果次数为0那么这个内存就不在被需要,内存需要释放掉。
               如: let obj = { name: "web" };  // 此时obj的引用为0
                       let a = obj;                         // 此时obj的引用为1
                       let b = obj;                         // 此时obj的引用为2
                       a = null;                             // 释放obj的引用,此时obj的引用为1,垃圾回收机制仍然不会将其回收
                       b = null;                             // 释放obj的引用,此时obj的引用为0,触发下个循环的垃圾回收机制。

                什么叫广度扫描呢?
                
                  在扫描一个对象是否被引用的时候采用广度的形式。所谓的广度跟深度是一种对比。广度的意思就是如上一个树的结构。A->B->D->C->E。深度则是A->B->C->D->E。

               老生代垃圾回收:
                     1.mark-sweep(标记清除)mark-compact(标记整理)二者是都在使用的,只是后者的使用频率没前者高。
                     2.老生代空间大,大部分都是活着的对象GC耗时长。
                     3.在GC期间无法响应,Stop-The-World。
                     4.V8的优化方案,增量标记,把一个大暂停换成多个小暂停。
               标记清除如下:
                     

               标记整理如下:

                        

                    执行多次标记清除就会执行一次标记整理。无论是标记清除还是标记整理或者是新生代的循环都是耗时比较久的。所以V8做了一个优化方案为增量标记。把一个大的阶段拆分成很多的小阶段去执行这样Stop-The-World的影响就可以降到最低了。

         7.三种方式的特点:

             回收算法                     Mark-Sweep(标记清除)     Mark-Compact(标记整理)      Scavenge(新生代互换)
               速度                                中等                                     最慢                                       最快
             空间开销                             少                                         少                                       双倍空间无碎片
         是否移动对象                          否                                         是                                           是

                

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值