V8垃圾回收

1,122 阅读3分钟

垃圾回收

原理

  • 执行环境会找出那些不再继续使用的变量,然后释放其占用的内存。

策略

引用计数垃圾收集

原理

  • 跟踪每一个值被引用的次数 此算法把“对象是否不再需要”简化定义为“对象有没有其他对象引用到它”。如果没有引用指向该对象(零引用),对象将被垃圾回收机制回收。

局限性

  • 循环引用 无法处理循环引用的事例。两个对象被创建,并互相引用,形成了一个循环。它们被调用之后会离开函数作用域,所以它们已经没有用了,可以被回收了。然而,引用计数算法考虑到它们互相都有至少一次引用,所以它们不会被回收。

    标记清除

原理

假定设置一个叫做根root的对象(在Javascript里,根是全局对象)。垃圾回收器将定期从根开始,找所有从根开始引用的对象,然后找这些对象引用的对象从根开始,垃圾回收器将找到所有可以获得的对象和收集所有不能获得的对象。

局限性

那些无法从根对象查询到的对象都将被清除 。

v8垃圾回收机制

栈内存的回收

栈内存调用栈上下文切换后,栈顶的空间就会自动被回收。操作系统会自动进行内存分配和内存释放。

堆内存的回收

新生代内存的回收

  • 副垃圾回收器 - Scavenge算法
  1. 标记活动对象和非活动对象
  2. 复制 from space 的活动对象到 to space 并对其进行排序
  3. 释放 from space 中的非活动对象的内存
  4. 将 from space 和 to space 角色互换

老生代内存的回收

  • 主垃圾回收器 - Mark-Sweep & Mark-Compact
  1. 标记阶段:对老生代进行第一次扫描,标记活动对象
  2. 清理阶段:对老生代进行第二次扫描,清除未被标记的对象,即清理非活动对象
  3. 活动对象整理阶段,将所有的活动对象往一端移动,移动完成后,直接清理掉边界外的内存。

优化 Orinoco

1. 增量标记

增量标记将原本的标记全堆对象拆分为一个一个任务,让其穿插在JavaScript应用逻辑之间执行。

2.懒性清理

将一次停顿进行的过程分为了多步,每次执行完一小步就让运 行逻辑执行一会,就这样交替运行。

3.并发

4.并行

新生代对象晋升到老生代的条件

  1. 第一个是判断是对象否已经经过一次Scavenge回收。若经历过,则将对象从From空 间复制到老生代中;若没有经历,则复制到To空间。
  2. 第二个是To空间的内存使用占比是否超过限制。当对象从From空间复制到To空间时, 若To空间使用超过25%,则对象直接晋升到老生代中。设置25%的原因主要是因为算法结束 后,两个空间结束后会交换位置,如果To空间的内存太小,会影响后续的内存分配。