垃圾回收

3/30/2022 render

# 1. 聊聊什么是内存管理?

查看答案

内存管理是开发者主动申请空间、使用空间、释放空间的过程。

js中基本数据类型(栈空间)由操作系统自动分配释放,引用类型(堆空间)由开发者分配释放。

# 2. 什么是内存泄露?

查看答案

内存泄露是空间不再使用缺没有释放的现象,会导致程序缓慢或崩溃。

一般不当使用闭包会导致内存泄露。

解决:
js中解决此类问题需要在使用完成后主动将变量置为null

# 2. 什么是垃圾回收机制

查看答案

GC是垃圾回收机制的简写,根据GC算法找到内存中的垃圾,并释放和回收空间

  • GC垃圾:程序中 不再需要使用的,程序中不能再访问的 对象
  • GC算法:垃圾回收查找垃圾和回收所遵循的规则

# 3. 常见的GC算法有哪些?

查看答案
  • 引用计数
  • 标记清除
  • 标记整理
  • 分代回收(V8用到的)

# 4. 引用计数的原理是什么?优缺点有哪些?

查看答案

原理:

  • 引用计数器,引用改变时修改引用数字
  • 判断当前引用数是否为0来决定是不是垃圾对象,如果是垃圾对象就进行回收

优点:

  1. 发现垃圾时立即回收
  2. 最大限度减少程序暂停,让空间不会有被占满的时候

缺点:

  1. 无法回收循环引用的对象
  2. 资源消耗开销大(对所有对象进行数值的监控和修改,本身就会占用时间和资源)

# 5. 标记清除的原理是什么?优缺点有哪些?

查看答案

原理:

  1. 标记阶段:遍历所有对象找活动对象(可达对象)标记(层次用递归进行操作)
  2. 清除阶段:遍历多有对象清除没有标记对象并抹掉第一个阶段标的标记
  3. 回收相应空间,将回收的空间加到空闲链表中,方便后面的程序申请空间使用

优点:

  1. 相对于引用计数算法来说解决对象循环引用的问题,局部作用域里面的内容无法被标记,所以即使有引用还是会被清除掉

缺点:

  1. 空间链表地址不连续(空间碎片化),不能进行空间最大化使用
  2. 不会立即回收垃圾对象,清除的时候程序是停止工作的。

# 6. 标记整理的原理是什么?优缺点有哪些?

查看答案

原理:
标记整理可以看做是标记清除的 增强

  1. 标记阶段:遍历所有对象找活动对象(可达对象)标记(层次用递归进行操作)
  2. 整理阶段:清除前先执行整理,移动对象位置,在地址上产生连续
  3. 清除阶段:遍历多有对象清除没有标记对象并抹掉第一个阶段标的标记
  4. 回收相应空间,将回收的空间加到空闲链表中,方便后面的程序申请空间使用

优点:

  1. 相较标记清除算法减少了碎片化空间

缺点:

  1. 不会立即回收垃圾对象,清除的时候程序是停止工作的。

# 7. PHP中如何解决引用计数循环引用的问题?

查看答案
  • PHP把变量使用unset后计数器不为0的变量看做疑似垃圾变量,记录在垃圾缓冲区中
  • 执行时机:当缓冲区满时会进行一次垃圾检查
  1. 模拟删除,递归模拟删除缓冲区的变量,使他们的计数器-1并且标记
  2. 模拟恢复,递归将所有标记的变量不为0的+1恢复
  3. 真实删除,将计数器为0的数据真实删除

如果一个变量只被自己引用,那么在unset之前的计数器是2,执行unset之后计数器为1,此时会被看做疑似垃圾变量。执行模拟删除之后计数器就会为0,此时就会进行真实删除。

# 8. 聊聊什么是JS垃圾回收机制

查看答案
  • JS的内存管理是自动的,每当我们创建对象、数组等,它就会自动的跟配内存空间。
  • 对象不再被引用时,或者对象已经存在,但是这些对象不能从根上访问(全局变量对象) 到时是垃圾。
  • 这个时候JavaScript会自动对这些垃圾进行空间的释放和回收,即JavaScript的垃圾回收。
  • js的垃圾回收依赖浏览器的垃圾回收机制。

# 9. V8的垃圾回收机制

查看答案

原始类型数据的回收由程序语言自身控制的,这里主要讨论的是存活在堆区的对象数据,这个过程是离不开内存操作的。

主要采用:

  1. 采用分代回收的思想
    • 内存分为新生代存储区、老生代存储区
    • 新生代区域主要存储存活时间较短的对象,老生代区域主要存储存活时间较长的对象
  2. 针对不同代采用不同的算法
    • 新生代的主要算法有:复制算法+标记整理法
      • 主要用空间换时间
      • 新生代区域分为两个大小的from和to空间
      • from空间是存活动对象,to是空闲空间
      • from使用到一定程度就会触发GC标记整理并将活动对象拷贝到to空间
      • 触发from空间回收
      • 将from和to空间进行名称调换重复上面的操作
    • 老生代的主要算法有:标记清除+标记整理+增量标记法
      • 增量标记:将一整段的垃圾回收操作标记拆分成多个小段完成回收,主要是为了实现程序和垃圾回收的交替完成,这样进行效率优化带来的时间消耗更加的合理。目前V8垃圾回收采用增量标记算法需要50ms,采用非增量标记算法需要1s。
      • 首要采用标记清除法,速度快。
      • 在晋升的时候,老生代的空间不够用的时候,会进行标记整理法。
  3. 一定机制下,新生代会向老生代区域晋升
    • 一轮GC之后还存活的对象要进行晋升
    • 拷贝过程中,to空间使用率超过25%时会全部晋升
更新时间: 2022-04-10 13:23