从JavaScript的垃圾回收机制谈起

javascript垃圾回收机制大家肯定都有所了解。网上大部分的文章也都是在讲引用计数算法和垃圾回收算法的原理以及这两者之间的区别。今天咱们不提这个,咱们只提关于老垃圾回收算法和新垃圾回收算法的演变。

一.旧的javascript垃圾回收算法:

我们以V8引擎为划分线。v8之前的浏览器的垃圾回收算法大概有三类:

1.引用计数(Reference Counting)算法(低版本ie下使用)
2.标记-清除(Mark-Sweep)算法
3.复制(copying)算法

我们先谈谈引用计数算法。顾名思义,引用计数算法的原理就是跟踪记录每个值被引用的次数。当声明一个变量将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向另一个时该值的引用次数便减一。当该值引用次数为0时就会被回收。它的缺点简单提提,循环引用时会引发内存泄露。
再谈谈标记-清除算法。当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。它的缺点是会产生小的内存碎片,而小的内存碎片再未来有大内存空间需要分配时是无法被利用的。
最后谈谈复制算法。此算法的出现是为了解决标记清除算法效率低下的问题,我们来看看原理。首先,此算法会将内存空间分为两部分,我们假设为A区域和B区域。先将所有的对象放置到A区中,在开始进行垃圾回收时,把A区中还需要留下来下次使用的对象转移到B区,然后将A区中剩余的对象清空,最后再将B区的对象转移到A区,以此类推。此算法效率奇高,但是要闲置一半的内存空间,实在是让人难以接受。

二.V8新生代垃圾回收算法:

V8的GC回收算法主要是将内存空间划分为了新生代和老生代,新生代主要采用Scavenge算,而Scavenge算法是基于Cheney算法实现的(Cheney算法就是基于上面我说copying算法);老生代采用的是Mark-Sweep&Mark-Compact算法。

1.新生代:Scavenge算法-Cheney算法.
2.老生代:Mark-Sweep&Mark-Compact算法.

我们先谈谈新生代里垃圾回收机制是怎么运行的。由于它是基于copying算法,那么原理就很显然了,它将新生代所占据的内存空间分成两部分FORM和TO,当垃圾回收开始时,来检查A区中的存活对象,然后将这些存货对象移入TO区中,再释放FORM区的内存。最后将FORM,TO对调。

Scavenge算法通过牺牲空间换时间的算法非常适合生命周期短的新生代,但是,当一个对象经过多次复制,生命周期较长的时候或则B空间不足的时候,对象会被分配到进入到老生代中,并采用新的算法进行垃圾回收。

那么老生代是如何运行的呢?
Mark-Sweep算法会在垃圾回收时遍历老生代空间中所有的存活对象,并标记他们。然后清除掉没有被标记的对象。而Mark-Compact则是用来处理标记清除后存在的内存碎片问题。它会将活着的对象往内存空间的一端移动,移动完成后直接清除边界外的内存,以此完成对碎片的回收。

除此之外还需要补充的一点是,对象晋升。其实就是新生代对象晋升到老生代对象的过程。
对象晋升主要发生在FORM空间复制对象到TO空间时期,在这期间主要有两个判断条件:

1.是否已经经历过Scavenge回收
2.TO空间的内存占用比是否超过25%

满足其中任意一个条件此对象就会晋升到老生代空间中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章