JS 性能优化(二) V8 引擎

V8 介绍

V8 是市面上主流得 JS 执行引擎,它采用即时编译得运行方式,提高了编译效率。它设有一个内存上限。在 64 位运行环境下,不超过 1.5G, 在32位环境下不超过 800M,在浏览器来说,再加上垃圾回收机制,这个内存大小是完全够用的,同时,如果空间过大的话,在垃圾回收过程中耗费的时间可能会被用户明显的感知到,造成卡顿。

V8垃圾回收策略

首先 v8 中采用了分代回收的思想,所谓分代回收即是把数据分成新生代和老生代,然后根据不同的对象采取不同的办法。操作如 图5.1

图5.1 分代回收策略图

新生代对象指那些存活时间较短的数据,如块作用域内的那些变量,老生代对象指的是存活时间较长的数据,如全局变量那些。

所以 V8 的内存空间分为两部分,较小的一部分用来存储新生代对象, 64x 环境下大小为 32M ,32x 环境下,大小为 16M 。较大的一部分用来存储老生代对象, 64x 环境下大小为 1.4G ,32x 环境下,大小为 700M

新生代回收过程:

在新生代的回收过程中主要采用了空间复制和标记整理算法。首先新生代的存储空间被分为两个等大的空间 From To 。当变量申请空间时,全去会申请在 From 空间内,让后对其进行标记整理,使得空间连续,避免浪费。然后把整理好的内容复制到 To 空间。最后让 From 空间和 To 空间进行交换并释放掉 From 空间的内容。然后把 From 空间可看作 To 空间,把 To 空间可看作 From 空间。

在空间复制过程中可能会存在一个晋升的操作,晋升也就是从新生代对象移动至老生代。能触发晋升操作的有两种情况。1. 一轮  GC 操作之后还存在的变量。 2. 当 To 空间的占用率超过 25% 时候,因为 To 空间 的占用率过多的话,当它变为 From 空间时可能无法存入新的变量。

老生代回收过程:

在老生代的回收过程中主要使用了标记清除,标记整理,标记增量。

在回收过程中主要采用了标记清除算法,这样操作对于性能速度的提升非常明显。当晋升操作时,且老生代存储空间不足时,就会触发一次标记整理。以获取更大的连续空间。最后采用标记增量的方法来进行效率提升。

所谓标记增量也就是把一次标记拆分成多次标记,因为 JS 的执行,和垃圾回收的过程是不可以同时进行的,如果一次标记内容过多,用户的体验必然不好。

同时可达对象不一定是第一层就可以访问到的,可能需要多层递进的访问,所以我们可以等程序执行到某一处引用时,然后对其进行标记。这样进行多次标记,给用户更好的体验。如 图5.2 所示,

图5.2 标记增量过程图

两者回收相比之下,新生代的思想是用空间换时间,基本上近半的空间不会用到,但是它的空间本就小,所以浪费一些可以接受。而且因为小,所以复制时候压力就小。 老生代的空间大,如果同新生代一样一分为二,不仅浪费空间难以承受,而且复制压力大。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。