第二节 V8
文章内容输出来源:拉勾教育Java高薪训练营
1.认识V8
- V8是一款主流的javascript执行引擎(高效执行javascript,优秀的内存管理机制)
- V8采用即时编译
可以直接把javascript源码翻译成能够执行的机器码
- V8的设置内存有上限
- 32位操作系统 800M
- 64位操作系统 1.5G
2. V8垃圾回收策略
基本类型数据,有javascript语言本身进行控制的
而现在讨论的回收主要是存放在堆区中的对象数据
- 策略
- 采用分代回收的思想
- 内存分为新生代和老生代
- 针对不同代的对象采用不同的算法进行回收,进行高效回收操作
- V8常用的GC算法
- 分代回收
- 空间复制
- 标记清除
- 标记整理
- 标记增量
3.V8如何回收新生代对象
3.1 新生代内存划分
- V8把内存空间一分为二如下所示
- 左侧,from和to区用来存放新生代对象
- 小空间用于存储新生代对象(
- 64位系统 32M
- 32位系统 16M
- 新生代指的是存活时间较短的对象
- 例如函数局部作用域中的对象
- 右侧,用来存放老生代对象
3.2 新生代回收算法
- 回收过程采用复制算法 + 标记整理
- 新生代内存区分为2个等大小空间
- 使用空间为From,空闲空间为To
- 活动对象存储于From空间
- 这时候To还是空闲的
- 一旦From的空间到达一定的大小之后,需要触发GC操作,算法为标记整理
- 标记整理后将活动对象拷贝至To
- 复制完成之后,就可以完全释放From空间(这时候就完成了新生代的回收操作)
- From与To交换空间完成释放
3.3 回收细节
- 拷贝过程中可能出现晋升操作
晋升操作是讲新生代对象移动至老生代进行存储
- 什么时候触发晋升
- 一轮GC还存活的新生代需要晋升
- form拷贝对象到To空间的时候,发现To空间的使用率超过25%
为什么是25%
将来进行回收操作的时候,最终是要把from空间和to空间进行交换,以前的to会变成from,以前的from会变成to
这就意味着我们的to使用率超过80%,那么它最终变成活动对象的储存空间之后,新的对象好像存储不进
to空间的使用率超过了一定限制,那么将来变成使用状态时,那么我们新进来的对象空间,好像不是那么够用了
4.V8如何回收老生代
4.1 老生代内存划分
- 老年代对象存放在右侧老生代区域
- 64位操作系统1.4G ,32为操作系统700M
- 老年代对象就是存活时间较长的对象
- 例如声明在全局的对象
- 或者是闭包存放的一些变量数据
4.2 老年代对象回收算法
-
主要采用标记清除
-
标记整理
-
增量标记算法
-
首先使用标记清除完成垃圾空间的回收
-
如果想把新生代的对象往老生代空间移动的时候,而且老生代的存储空间不足以存放新生代存储区所移过来的对象
-
这个情况下就会触发标记整理进行空间优化
-
采用增量标记进行效率优化
4.3 增量标记
当GC执行垃圾回收的时候,会阻塞当前javascript的程序执行,所以在这里会有一个空档期
1.程序执行完之后,程序会停下来,执行当前的回收操作
2.所谓的标记增量,就是把一整段的垃圾回收操作拆成几步,组合的完成整个回收
3.从而替代我们之前一口气做完的垃圾回收操作
4.这样的好处就是程序和垃圾回收,交替的执行
5.虽然这样看来程序停顿了好多次,但是V8在内存达到1.5G的时候,执行垃圾回收采用非增量标记的形式的时间不会超过1s
6.所以垃圾回收机制的这一小段的时间间隔是非常小的,合理的,用户无感知
4.4 细节对比
因为新生代使用复制算法,所以新生代区域垃圾回收使用空间换时间
新生代区域存储空间很小,浪费一点空间,相对于时间上的提升,微不足道
老生代存储区域比较大,垃圾回收不适合复制算法,而且存放的数据会比较多,使用复制算法会消耗的时间会比较多