老生代空间说明
右侧红色区域就是来生代存储区,针对老生代区域在 V8 当中同样是有一个内存大小的限制。在64位操作系统当中是 1.4G 、在32位操作系统中是 700M,有了这样一个大小之后就可以往它里面去存放具体的数据。而老生代对象其实指的就是当前存活时间较长的对象,至于说哪些对象事呢?例如,之前所提到的在全局对象下所存放的一些变量、闭包放置的一些变量数据有可能也会存活很长时间。
老生代如何完成垃圾回收的?
针对老生代采用的垃圾回收策略是:标记清除算法、标记整理算法、增量标记算法。具体来说怎么使用呢,其实它主要采用的是标记清除算法完成对应垃圾空间的释放回收。之所以会使用标记清除,是因为相对于空间碎片它在效率提升上是非常明显的。在什么时候会使用到标记整理算法呢?非常简单,如果说我们发现当它去想把新生代区域里面的内容往当前老生代存储区进行移动的时候而且这个时间节点上,老生代存储区域空间又不足以来存放新生代存储区所移过来的这些对象,也就是之前所提到的晋升。在这种情况下就会触发标记整理,然后把之前的一些碎片空间进行整理回收,这样的话就让我们又更多空间可以进行使用。说到这我们就大致的知道了对应当前的 V8 来讲针对与老生代的一个对象回收,其实主要采用的还是标记清除,当我们想去把新生代对象往老生代存储区域进行移动的时候,如果出现了空间不足的情况就会触发标记整理的操作。最后它还会采用增量标记的方式对当前这样一个回收效率进行提升。
老生代与新生代回收策略对比
新生代的垃圾回收策略是用空间换时间:因为它采用的是复制算法,也样也就意味着每时每刻它的内部都会有一个空闲空间的存在。由于新生代存储区它本身的空间就很小,所以分出来的空间就更小这一部分的空间浪费,相对于它所带来的时间上的提升是微不足道的。在老生代对象回收过程中为什么不去采用这种一分为二的做法呢?非常简单,因为老生代存储区域空间比较大的,如果说一分为二基本上就有几百兆空间是浪费不用的。再者老生代存储的数据比较多,在复制的过程中消耗的时间也就非常的多。由此可见,老生代不适合使用复制算法来实现。
标记增量如何优化垃圾回收?
如图所示整个回收操作分成两个流程,一个是程序的执行一个就是当前垃圾的回收。在这我们要明确的就是当垃圾回收进行工作的时候,它其实会阻塞 JS 脚本的执行,所以图中会出现空档期。所谓的标记增量指的是,简单点说就是将当前一整段的垃圾回收操作拆分成多个小步,组合着完成当前整个回收。从而去替代之前一口气做完的垃圾回收操作,这样做的好处通过这个图也能看的非常明显,主要就是让我们可以实现垃圾回收与程序执行交替着完成。而不是像以前那样程序执行的时候就不能做垃圾回收,而程序去做垃圾回收的时候就不能去做程序的运行。这样所带来的时间消耗会更加的合理一些,简单的去举个例子看下增量标记的实现原理:从左侧开始程序在运行的时候不需要去执行垃圾回收的,一旦当它触发了垃圾回收之后这一块无论采用的是何种算法在这里它都会去进行遍历和标记的操纵。这里需要注意因为我们针对的是老年代存储区域,所以它就会存在遍历操作在遍历过程中,它要做标记这个标记可以不一口气做完。因为存在着直接可达和间接可达操作,也就是说如果我们在做的时候直接第一步先找到第一层的可达对象就可以停下来了。让程序再去执行一会,如果说程序执行完一会之后再继续去让我们的GC机制去做第二步的标记操作。比如它的下面会有一些子元素,也是可达的就会继续做标记。标记一轮以后再让 GC 停下来继续回到程序执行,这也就是所谓的交替执行。到最后标记操作全部完成,最终去完成垃圾回收。并在完成垃圾回收操作之后程序回到它该执行的地方接着去做,虽然这样开来可能让你觉得当前 的程序停顿了很多次,但是你要明白我们整个 V8 最大的垃圾回收当他达到 1.5G 时候采用非增量标记的形式时间也不超过 1 秒钟,所以以上的执行间断间隔是合理的,而且这样一来的话它就最大限度的把以前很多长一段时间的停顿时间直接拆分成了更小段。这种对于用户来说就会显得更加的好一些。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!