浏览器的垃圾回收机制

147 阅读2分钟

垃圾回收简称GC(Garbage Collection)

js中,基础数据类型存储在栈内存中,引用数据类型存储在堆内存中,不同的内存有不同的垃圾回收机制。

栈和堆的区别

栈(stack)内存由系统自动分配固定的内存空间,遵循先进后出原则。

特点:线性有序存储,容量小,分配效率高。

堆(heap)内存由系统动态分配不固定的内存空间,不会自动释放。

特点:无序的树状结构,容量大,分配效率底。(因为先开辟空间,再将堆地址存入栈内存中)

栈内存的GC

栈内存就是执行栈,执行栈存储的是执行上下文。

每执行一个函数,函数的执行上下文会被压入栈中。

栈内存有个记录当前执行状态的指针ESP,指向调用栈中正在执行的函数的执行上下文。

当函数执行完毕后,ESP指针下移,函数的执行上下文就会出栈。

堆内存的GC

堆内存的垃圾回收机制用的是V8的垃圾回收器进行内存回收。

V8采用的是分代式垃圾回收机制。

分代是指将堆内存分为新生代和老生代,新生代中的对象为存活时间较短的对象,老生代中的对象为存活时间较长或长驻内存的对象。

新生代老生代
新生代

新生代主要采用scavenge算法进行垃圾回收,而scavenge算法具体实现采用的是cheney算法。

cheney算法是一种采用复制的方式进行垃圾回收。该算法将堆内存一分为二,每个空间称为semispace,一个semispace处在使用状态为From空间,一个semispace处在闲置状态为To空间。

分配对象时,先分配在From空间。垃圾回收时,会检查From空间中的存活对象,将存活对象复制到To空间中,完成复制后,From空间和To空间角色发生转换。没有被复制的非存活对象将被释放。

semispace(From)semispace(To)老生代

scavenge的缺点:只能使用堆内存的一半。

老生代

老生代采用标记清除(Mark-Sweep)和标记整理(Mark-Compact)结合的方式进行垃圾回收。

Mark-Sweep分为两个阶段,标记阶段:遍历堆中的对象,并标记存活对象;清除阶段:清除没有标记的对象。

每次Mark-Sweep后会存在内存碎片,所以有了Mark-Compact。

Mark-Compact是Mark-Sweep演变而来,区别是标记存活对象后,将存活的对象移到一端,而后清除另一端。

新生代晋升老生代

晋升条件:

  1. 该对象是否经历过scavenge回收
  2. To空间占比超过25%