V8
概念
垃圾回收机制
引用计数法
优点:
- 可即刻回收:当被引用数值为 0,对象马上会把自己作为空闲空间连到空闲链表上。也就是说,在变成垃圾的时候就立刻被回收
- 因为是及时回收,那么程序不会暂停去单独使用很长一段时间的 GC,那么最大暂停时间很短
- 不用去遍历堆里面的所有活动对象和非活动对象
缺点:
- 计数器需要占很大的位置
- 最大的劣势是无法解决循环引用无法回收的问题
标记清除法
优点:实现简单,解决了循环引用的问题
缺点:
- 造成内存碎片化
- 再分配时遍历次数多,如果一直没有找到合适的内存块大小,那么会遍历空闲链表(保存堆中所有空闲地址空间的地址形成的链表)一直遍历到尾端。
标记清除是浏览器常见的垃圾回收方式,当变量进入执行环境时,就标记这个变量“进入环境”,被标记为“进入环境”的变量是不能被回收的,因为他们正在被使用。当变量离开环境时,就会被标记为“离开环境”,被标记为“离开环境”的变量会被内存释放。
V8 对 GC(Garbage Collection)的优化
分代式垃圾回收
V8 采用分代式垃圾回收策略,将堆内存分为新生代和老生代,分别采用不同的垃圾回收器来管控。新生代的对象存活时间短,占内存小,老生代的对象存活时间长,占内存大
新生代垃圾回收
- 垃圾回收管理器将新生代的内存一分为二,分别是
使用区
和空闲区
- 新加入的内存会存放到使用区,当使用区块被写满时执行一次垃圾回收
- 新生代垃圾回收器对使用区的活动对象进行标记,将使用区的活动对象复制进空闲区并进行排序,将非活动对象占用的空间清理掉
- 角色互换,把原来的使用区变成空闲区,把原来的空闲区变成使用区
- 当一个对象经过多次复制后依然存活,它将会被认为是生命周期较长的对象,随后会被移动到老生代中
- 复制一个对象到空闲区时,空闲区空间占用超过了 25%,那么这个对象会被直接晋升到老生代空间中
老生代垃圾回收
- 标记阶段,从一组根元素开始,递归遍历这组根元素,遍历过程中能到达的元素称为活动对象
- 清除阶段,将非活动对象清除掉
- 标记结束后,将活着的对象(即不需要清理的对象)向内存的一端移动,最后清理掉边界的内存
并行回收(Parallel)
新生代对象空间就采用并行策略,在执行垃圾回收的过程中,会启动了多个线程来负责新生代中的垃圾清理操作,这些线程同时将对象空间中的数据移动到空闲区域,这个过程中由于数据地址会发生改变,所以还需要同步更新引用这些对象的指针,此即并行回收。
这个过程中,主线程处于全全停顿的状态,不需要考虑内存中对象的引用关系改变