专栏名称: 前端大全
分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯
目录
相关文章推荐
龙视新闻联播  ·  龙江最美飘雪时|早春升温日 赏冰乐雪时 ·  13 小时前  
前端之巅  ·  Dagger:我们用 GO 和 ... ·  昨天  
前端早读课  ·  【第3457期】揭秘!如何将动效描述自动转化 ... ·  3 天前  
51好读  ›  专栏  ›  前端大全

V8 内存分配与垃圾回收

前端大全  · 公众号  · 前端  · 2017-08-28 20:35

正文

(点击 上方公众号 ,可快速关注)


作者:一像素

www.cnblogs.com/onepixel/p/7422820.html

如有好文章投稿,请点击 → 这里了解详情


V8 将内存空间主要分为:新生代 和 老生代 两种 。

1、新生代空间

新生代空间中的对象为存活时间较短的对象,大多数的对象被分配在这里,这个区域很小但是垃圾回特别频繁 。

它将堆内存一分为二,每一部分空间称为 semispace,其中一个处于使用状态(from 空间),另一个处于闲置状态(to 空间)

对于新产生的对象,将从 from 空间中分配内存 。

新生代分配内存非常容易,我们只需要保存一个指向内存区的指针,不断根据新对象的大小进行递增即可。当该指针到达了新生代内存区的末尾,就会触发一次垃圾回收。

新生代的垃圾回收采用 Scavenge 算法 ,其工作原理如下:

首先检查 from 空间,将存活对象复制到 to 空间,非存活对象将会被释放。完成复制后,from 空间和 to 空间角色发生转换。新产生的对象始终从 from 空间中分配内存,to 空间则处于闲置状态。当再次进行垃圾回收时,也会执行和第一次同样的操作,如果存在以下两种情况,存活对象就会被复制到老生代空间中,这个过程称为 对象晋升

  • 存活对象已经经历过一次 Scavenge 回收 。

  • to 空间内存占用比例超过 25% (保证下次新对象有足够的空间可分配)


2、老生代空间

老生代空间中的对象为存活时间长或常驻内存对象,大多数从新生代晋升的对象会被移动到这里。

老生代占用内存较多,如果使用 Scavenge算法,不仅会浪费一半空间,复制如此大块的内存消耗时间将会很长,所以 Scavenge 算法显然不适合。

V8 对于老生代中的垃圾回收,采用 Mark-Sweep (标记清除) 和 Mark-Compact(标记整理) 相结合 。

(1) Mark-Sweep

Mark-Sweep 分为 标记 和 清除 两个阶段 。

在标记阶段需要遍历堆中的所有对象,并标记那些活着的对象,然后进入清除阶段。在清除阶段,只清除没有被标记的对象。由于标记清除只清除死亡对象,而死亡对象在老生代中占用的比例很小,所以效率较高。

标记清除存在的问题是,进行一次标记清除后,内存空间往往是不连续的,会出现很多的内存碎片。如果后续需要分配一个需要内存空间较多的对象时,如果所有的内存碎片都不够用,将会使得V8无法完成这次分配,提前触发垃圾回收。

(2) Mark-Compact

标记整理正是为了解决标记清除所带来的内存碎片的问题。标记整理在标记清除的基础进行修改,将其的清除阶段变为紧缩极端。在整理的过程中,将活着的对象向内存区的一段移动,移动完成后直接清理掉边界外的内存。紧缩过程涉及对象的移动,所以效率并不是太好,但是能保证不会生成内存碎片。

3、三种回收策略比较

从图中可以看出,在 Mark-Sweep 和 Mark-Compact 之间,由于 Mark-Compact 需要移动对象,所以它的执行速度最慢。

所以在取舍上,V8 主要使用 Mark-Sweep,在空间不足以对新生代中晋升过来的对象进行分配时才使用 Mark-Compact 。

4、垃圾回收引起的性能问题

为了避免出现 JavaScript 应用逻辑 与 垃圾回收操作 产生不一致的冲突,垃圾回收的三种基本算法都需要将应用逻辑暂停下来,待垃圾回收完成后,再恢复执行应用逻辑,这种行为被称为 全停顿 。

按官方说法,以 1.5G 的垃圾回收堆内存为例,V8 做一次小的垃圾回收需要 50ms 以上,做一次非增量式垃圾回收甚至需要 1s 以上。这是垃圾回收中引起的 JavaScript 线程暂停执行时间,在这样的时间花销下,应用性能和响应能力都会直线下降。

在 V8 的分代式垃圾回收中,一次小垃圾回收只收集新生代,由于新生代默认配置的较小,且其中活动对象通常较少,所以即便它是全停顿,影响也不大。

但 V8 的老生代通常配置较大,且存活对象较多,全堆垃圾回收的标记、清理、整理等动作造成的停顿就会比较严重。

为降低全堆垃圾回收而导致的停顿时间,V8 做了以下改善措施:

(1) 限制堆内存大小







请到「今天看啥」查看全文