garbageCollection

栈中垃圾回收

记录当前执行上下文状态的指针称为ESP

JavaScript引擎通过向下移动ESP来销毁该函数保存在栈中的执行上下文

堆内存中的垃圾回收

代际假说:(The Generational Hypothesis)
1.大部分对象在内存中的时间很短,简单来说,就是很多对象一经分配内存,很快就变得不可访问;
2.不死的对象,活的更久

v8引擎会把堆分成新生代和老生代两个区域,新生代放置生存时间短的(大小通常为8M),老生代放置存活时间长的对象
(容量一般大于8M)

垃圾回收器

1.副垃圾回收器,只要负责新生代的垃圾回收
副垃圾回收器中的对象通常是较小的对象,区域不大,但是回收频繁。
新生代中使用Scavenge算法,将新生代的区域分为2半,一半为对象区域,一半为空闲区域
新的对象会被加入到对象区域,当对象区域快写满时,就要进行一次垃圾回收。
对象区域中的垃圾进行标记-> 副垃圾回收器将活动对象复制到空闲区域,同时会将对象有序的排序(不会产生内存碎片的原因)
->将对象区域与空闲区域的角色进行翻转

2.主垃圾回收器,主要负责老生代的垃圾回收
新生区中晋升的对象,一些大的对象会直接被分配到老生区。因此老生区中的对象有两个特点,一个是对象占用空间大,另一个是对象存活时间长。
主垃圾回收器采用的是标记-清楚算法( Mark-Sweep )
从根元素开始,递归根元素(不能到达的元素,标记为垃圾)->直接对垃圾数据进行回收
标记 - 整理( Mark-Compact )
让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存

回收器的工作流程

1.标记空间中的活动对象与非活动对象,活动对象就是还在使用的对象,非活动对象就是可以进行垃圾回收的对象
2.回收非活动对象所占据的内存。。其实就是在所有的标记完成之后,统一清理内存中所有被标记为可回收的对象。
3.内存整理。垃圾回收之后,内存中会存在大量不连续的内存空间称为内存碎片(不是所有的回收器都会产生内存碎片,例如副垃圾回收器)

对象晋升策略

当一个对象经历过2次垃圾回收依然存在,会被移动到老生代中

全停顿

由于 JavaScript 是运行在主线程之上的,一旦执行垃圾回收算法,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。我们把这种行为叫做全停顿(Stop-The-World)

为了降低老生代的垃圾回收而造成的卡顿,V8 将标记过程分为一个个的子标记过程,同时让垃圾回收标记和 JavaScript 应用逻辑交替进行,直到标记阶段完成,我们把这个算法称为增量标记(Incremental Marking)算法


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!