javascript的垃圾回收(GC)和V8

253 阅读3分钟

javascript中的内存管理是自动的,对象不再被引用时就是垃圾,对象不能从根上访问到时也是垃圾。
首先我们得先明白一些概念
什么是可达对象?
可达对象就是能从根出发访问到的对象,根就是全局变量对象。
GC里的垃圾是什么?
1.程序中不再使用的对象
2.程序中不能在访问到的对象

明白了这些,那常用的GC算法有哪些呢?
1.引用计数
2.标记清除
3.标记整理
4.分代回收

引用计数算法

设置引用数,判断当前引用数是否为0;当一个对象的引用关系改变时,引用计数器就会修改引用数字
引用计数算法的优点:
1.发现垃圾时立即回收
2.最大限度减少程序暂停
引用计数算法的缺点:
1.是没办法回收循环应用的对象
2.时间开销大

标记清除算法

遍历所有对象找到活动对象进行标记,遍历所有所有对象清除没有标记的对象
标记清除算法优点:
1.可以清除循环引用的对象
标记清除算法缺点:
1.会造成空间的碎片化

标记整理算法

标记整理可以看做是标记清除的增强,标记阶段和标记清除算法一致,清除阶段会先执行整理,移动对象位置

分代回收

内存分为新生代和老生代,针对不同对象采用不同的算法

1635773134(1).jpg

说完所有的算法,那咱们大名鼎鼎的V8引擎到底用了哪些算法呢?
v8常用的GC算法:分代回收、空间复制、标记清除、标记整理、标记增量

v8是一款主流的javascript执行引擎,v8采用即时编译,可以直接把代码先翻译成字节码,再编译成机器码,所以效率很高,v8内存有上限,64位操作系统 1.5G,32位操作系统 800M。

v8内存分配:
1.v8内存空间一分为二
2.小空间用于存储新生代对象(32M|16M)
3.新生代指的是存活时间较短的对象

1635773009(1).jpg

新生代对象回收实现原理:
1.回收过程采用复制算法+标记整理
2.新生代内存区分为2个等大小空间
3.使用空间为from,空闲空间为to
4.活动对象存储于from空间
5.标记整理后将活动对象拷贝至to
6.from中剩下的对象就是不可达的,直接释放from空间
7.再将from与to空间交换,就实现了清除

老生代存储区说明: 1.64位操作系统1.4G, 32位操作系统 700M 2.老生代存储对象就是存活时间较长的对象

老生代对象回收原理:标记清除、标记整理、增量标记算法
1.首先使用标记清除完成垃圾回收
2.当新生代对象晋升时,发现老生代存储区不够存储,这时候会采用标记整理进行空间优化
3.采用增量标记进行效率提升,主线程执行代码时会做垃圾回收,垃圾回收操作会是线程阻塞,如果垃圾回收时间过长,页面就会出现明显的卡顿。标记增量算法就是把我们一口气执行的垃圾回收操作拆分成多个小任务组合去完成整个过程。可达对象的标记过程分步完成

1635773950(1).jpg