认识V8
- V8是目前市面上最主流的JS执行引擎
- 目前我们的chrome浏览器,nodejs平台都在采用
- JS之所以能在上边高效的工作,正是因为V8的存在
- V8采用即时编译
- 之前的引擎都需要先将我们的JS代码转为字节码,然后才能去执行,对于V8来说,可以直接将源码直接翻译为我们当前可以直接执行的机器码,所以这个时候的速度是非常快的
- V8内存设有上限
- V8的内存空间设置了一个数值,在64位的操作系统上不能超过1.5G,对于32位来说这个数值不能超过800MB的
- 为什么
- V8本身就是为了浏览器来去制造的,所以现有的内存大小对于网页应用来说是足够的
- V8内部所去使用的一个垃圾回收机制决定了采用这样一个设置是合理的,因为官方做过这样一个测试,当我们的垃圾内存达到1.5G的时候,如果V8去采用增量标记的算法进行垃圾回收只需要消耗50ms,而如果采用非增量标记的话则需要1s,从用户体验来说,1s其实已经算是很长的时间了,所以V8就是用1.5G为界限了
V8垃圾回收策略
- 前置描述:我们都知道,在程序的使用过程中,我们会用到很多数据,而这些数据我们可以分为原始数据和对象类型的数据,对于这些基础的原始数据来说,都是由程序的语言自身来进行控制的,所以在这里我们所提到的回收,主要还是指的是当前存活在我们堆区里的对象数据,因此这个过程我们是离不开对象操作的,而我们当前也知道,在V8当中,他对内存是做了上限的,所以我们接下来主要看一下他是怎样对垃圾进行回收的呢
- 采用分代回收的思想 — 把我们当前的内存空间区按照一定的规则分成两类,一个是新生代存储区,一个是老生代存储区,至于如何划分我们后续会介绍到,有了这样的一个划分之后,它就会根据不同代采用更高效的一种GC算法,从而对不同对象进行一个回收的操作
- V8常用GC算法
- 分代回收 — 必须用到,因为要去做空间分代
- 空间复制 — 后续会介绍
- 标记清除
- 标记整理
- 标记增量 — 为了提高效率
V8如何回收新生代对象
概述
- V8内存空间一分为二
- 小空间用于存储新生代对象(32MB || 16MB)
- 新生代指的是存活时间较短的对象
- 局部作用域内的变量就属于新生代
回收流程
- 回收过程采用复制算法 + 标记整理
- 首先将左侧的小空间也一分为二,大小相同
- 使用空间为From,空闲空间为To
- 将所有的变量对象都分配在From空间
- 现在To是空闲状态,一旦我们的From空间应用到一定程度,去触发GC操作,这时会采用标记整理的操作将活动对象拷贝至To
- 拷贝完成就意味着我们之前的From空间的对象有了一个备份,这时就可以考虑做一些回收操作了
- 将From空间进行完全的释放,因为From里的对象在To里边有一个备份,From直接释放掉就不存在任何问题
- 这时新生代对象就完成了一个回收操作
回收细节说明
- 拷贝过程中可能出现晋升
- 如果我们在拷贝时发现某一个变量对象所指定的空间呢,他在我们当前的老生代对象里边也会出现,这时我们就会出现一个所谓的 晋升 的操作
- 晋升就是将新生代对象移动至老生代
- 一轮GC还存活的新生代需要晋升
- 当前在拷贝的一个过程中发现To空间的使用率超过了25%,那么在这时我们也需要将这一次的活动对象移动至老生代
- 为什么是25%?
- 因为我们在将来进行回收操作的时候需要把Form空间和To空间进行一个交换,也就是说以前的To会变成From,以前的From会变为To,这也就意味着我们的To使用率如果达到了80%,那么最终他变成活动对象的存储空间后,新的对象就存不进来了
- 为什么是25%?
V8如何回收老生代对象
概述
- 老生代对象存放在右侧老生代区域
- 针对于老生代区域,在V8当中同样有一个内存大小的限制
- 64位操作系统1.4G,32位操作系统700MB
- 老生代对象其实指的就是当前存活时间较长的对象
- 例如:全局对象下的变量,闭包内的变量数据
回收流程
- 主要采用标记清除,标记整理,增量标记算法
- 首先使用标记清除完成垃圾空间的回收
- 存在空间碎片化的问题
- 如果我们发现当他去想把我们新生代区域的内容,往老生代进行移动的时候,而且这个时间节点上我们老生代存储区域的共建又不足以来存放新生代存储区所以移动过来的对象,也就是我们之前提到过的晋升,这种情况就会触发标记整理,将之前的碎片化空间整理为地址上是连贯的
- 采用增量标记进行效率优化
回收细节对比
- 新生代区域垃圾回收使用空间换时间
- 采用的是复制算法,意味着每时每刻内部都会有一个空闲空间的存在,但是由于新生代存储区,本身的空间就很小,所以分出来的空间就更小,所以这部分空间的浪费,相对于带来的时间上的提升是微不足道的
- 老生代区域垃圾回收不适合复制算法
- 老生代空间很大,一分为二的话就有几百MB的空间是浪费不用的,这样就太过于浪费
- 老生代空间存储的数据其实比较多,所以在复制时消耗的时间也会更多
V8垃圾回收总结
- V8是一款主流的JS执行引擎
- V8内存设置上限
- 本身是针对与浏览器设置的,所以在webAPP上,这个内存是充足的
- 内部的垃圾回收机制来决定,如果内存再放大,那垃圾回收时间就可能会超过用户的感知,影响体验
- V8采用分代回收思想实现垃圾回收
- 新生代
- 老生代
- V8垃圾回收常见的GC算法
- 新生代
- 复制算法 + 标记整理算法
- 老生代
- 标记清除算法 + 标记整理算法 + 增量标记算法
- 新生代