V8 垃圾回收 简单理解

389 阅读2分钟

垃圾回收——Garbage Collection

栈内存由操作系统管理,而GC都是指堆内存。

主流引擎:
Trident内核:

IE,360,搜狗,TT,The World,MaxThon

Gecko内核:

NetScape6及以上,FF,MoziliaSuite/SeaMonkey

Presto内核:

Opera7及以上,Opera原为Presto,现为Blink

WebKit内核:

Safari,Chrome[Chrome的Blink为WebKit的分支]

现在基本的浏览器JavaScript引擎(如V8 和 SpiderMonkey)都实现了GC。

简单介绍三种常见GC算法:

1、Mark-and-Sweep 标记清理

标记变量状态,对于处于执行期上下文的标记为活跃,其余标记为“待清理”。随后,垃圾回收器将标有“待清理”的变量统一清理,释放内存。

  1. 标记
  2. 清理
2、Mark-Compact 标记整理

使用标记整理,可以解决内存碎片化问题,提高内存使用效率。该算法标记阶段耗时严重,易阻塞主线程。 将标记的活跃对象往内存的一端移动,此过程可能会改变内存中对象地址。

  1. 标记
  2. 整理
  3. 清理
3、Reference-counting 引用计数

此算法已经废弃,标记对象引用次数,将计数为0的清理

  1. 计数
  2. 清理 此算法无法解决循环引用的情况,容易造成内存泄漏。

image.png

V8中的GC

V8是Google开源的C++编写高性能JavaScript引擎

将堆内存(Heap memory)分成几个区域

主要的如下:

New Space: Cheney算法,内存分两块,一个使用状态:From空间, 一个闲置状态:To空间。广度优先算法,查找From中活跃的,向To空间转移。遍历算法是广度优先算法

Old Space: Mark-Compact算法,为解决标记耗时问题,采用增量标记(Incremental marking)特性。将标记工作分成多个小段,夹杂在主线程逻辑中。

image.png

增量标记需要通知垃圾回收器更新标记,通知也需要消耗成本。

另外 V8 使用 Worker thread 实现了 平行标记并行标记,也是解决标记耗时的手段。

隐藏类

每一个对象都有一个隐藏类,用于提升对象性能。记录对象的特征和属性关系映射。

我们创建对象时,拥有完全相同特征的对象可以共享一个隐藏类。当然隐藏类也需要占用内存空间。

我们要尽量避免动态增删对象属性操作,在构造函数内一次性声明所有需要用到的属性,如果不需要某属性,可以置null。

相同名称的属性尽量按照相同顺序声明,可以尽可能地让更多对象共享相同的隐藏类。即使不能共享隐藏类,也可以减少隐藏类分支的创建。

参考文章:

《JavaScript 高级程序设计(第4版)》

liujiacai.net/blog/2018/0…