All Articles

V8 Blog | Orinoco: young generation garbage collection 2017-11-29

1. 原文

Orinoco: young generation garbage collection

2. 摘要翻译

前部分大段介绍基础的Node内存回收机制,这部分就不翻译了,可以查看阿里的博文:

因为新生代内存空间非常非常小(封顶16M),这部分内存经常被快速耗尽,需要频繁执行内存回收。在M62版本之前,V8使用semispace拷贝的回收机制,将内存一分为二,同时只使用其中的一半,存活的对象会被拷贝,剩余的空间会被回收,然后存活两次的对象将会被晋升到老生代。

M62号版本开始,V8将会调整默认的新生代内存回收算法,调整成Parallel Scavenger算法(a parallel Scavenger),类似于Halstead’s semispace copying collector

下文会解释:

  • the single-threaded Cheney semispace copying collector 现在在使用的新生代内存回收算法
  • a parallel Mark-Evacuate scheme 借鉴老生代算法的并行回收算法
  • the parallel Scavenger 准备实装的并行回收算法

Single-threaded Cheney’s Semispace Copy

在M62号版本之前,V8使用的Cheney’s semispace copying algorithm非常适合单核心的可执行程序,并且也非常合适一个代际回收的内存回收机制。

… 后面都在解释之前的新生代内存回收机制。这里就不翻译了。

Parallel Mark-Evacuate

我们之前基于V8的完整Mark-Sweep-Compact算法,试验了并行的Mark-Evacuate回收算法。主要的好处是可以利用成熟的Mark-Sweep-Compact算法的思路体系。

这个算法分三个步骤:

  • marking 标记
  • copying 拷贝
  • updating pointers 修正指针

为了避免sweeping内存页并维护一张可用内存的free list,新生代内存仍旧使用semispace的方式进行内存compact来回收内存空间。新生代内存初始由并行的方式进行标记,标记完成后存活对象会被并行地拷贝到对应的空间内。这个工作会分布式地在逻辑内存页上进行。每个线程都专注于拷贝他们自己的buffer(local allocation buffers (LABs))。拷贝完成后,同样的并行操作模式会应用在更新指针上。这三个步骤是一步接一步的,虽然每个步骤内都是并行的,但步骤之间还是必须按顺序执行。

Parallel Scavenge

这个回收算法的大意是指:

  • Parallel Mark-Evacuate算法分离了扫描标记存活对象、拷贝存活对象、更新指针这几个步骤
  • Parallel Scavenge则是将上述几个步骤合而为一,这么做的话就可以完全利用工作线程,进一步提升效率,也是M62版本开始V8使用的新生代垃圾回收算法

Results and outcome

Total young generation garbage collection time (in ms) across various websites:

该新算法减少了20%-50%的新生代垃圾回收时间(V8 now ships with the parallel Scavenger which reduces the main thread young generation garbage collection total time by about 20%–50%)

EOF

Published 2018/3/21

Some tech & personal blog posts