1.什么是v8引擎
- v8引擎是谷歌开源的高性能的javaScript引擎,用C++编写。它被设计用来提高网页浏览器内部JavaScript执行的性能,但同时又不局限使用在浏览器中,可以独立运行,或者可以嵌入C++的应用程序中。
- v8引擎实现了ECMA-262中规定的ECMAScript
- v8高性能的特性:JIT编译、垃圾回收、内联缓存、隐藏类
2.内存如何存储数据
javaScript中包含8种数据类型:Number 、 Boolean 、 Null 、 String 、 Symbol 、 Undefined 、 BigInt 、 Object ,其中object为引用数据类型,其余七种则是基本数据类型,这也就造成了它们存储的差异性。
javaScript是一门动态、弱类型的语言,动态指的是在运行过程中才去确认其变量的数据类型,弱类型语言指该语言支持隐式类型转换,如四则运算、if语句
运行js代码的时候从内容空间上分为堆空间和栈空间,这里栈空间就是创建执行上下文的调用栈。
function foo() {
let a = 1;
let b = 'test';
let c = {
num: 3;
}
let d = c
}
foo()
当执行这段函数时,先编译,创建执行上下文,然后逐行执行赋值代码,基本数据类型的数据就存放在在了调用栈中
然后执行到引用数据类型的赋值时,将该对象分配到堆空间中,分配后会有一个对应的内存地址,将这个内存地址赋值给变量,并存到栈空间中,这样就完成了基本数据类型和引用数据类型的存储 之所以要将基本数据类型存到栈空间中,而引用类型存到堆空间中,是因为在执行完foo函数后,切换当前执行的上下文过程中如果存放的数据体积较大,势必会影响整个程序的执行效率,所以栈空间的体积较小,堆空间中存放数据较多,体积大。3.V8的垃圾回收
垃圾数据:当存放到内存的数据不再被使用的时候,这些数据就成为了垃圾数据,如果这些垃圾数据不被清理的话,会一直占用内存,导致内存越用越多,直至发生内存溢出,影响程序运行。
垃圾回收分为手动回收和自动回收两种策略。手动回收就是内存分配和回收都是由代码控制,如C、C++,使用自动回收则是由垃圾回收器来自动释放内存空间,如JavaScript、Java、Python。
回收栈空间中的垃圾数据
function foo(){
let a = 1;
let b = 3:
function bar(){
let c = 3;
let d = {
name: 'job'
}
}
bar()
}
foo()
执行这段代码后,会依次向调用栈中推入foo和bar这两个执行上下文,程序执行到哪个函数时,就会有一个记录当前执行状态的指针(称为(ESP)指向该函数的执行上下文,当bar函数执行完毕后,ESP则下移指向foo函数的执行上下文,此时之前存放bar函数执行上下文的内存就无效了,如果后续有新的函数推进来,则会覆盖掉bar函数的之前使用的内存,因此javaScript引擎是通过移动ESP来清除栈中垃圾数据
回收堆空间中的垃圾数据
堆中垃圾数据是通过javaScript引擎垃圾回收器来回收,V8把堆分成了新生代和老生代两个区域,新生代存放生存时间短的对象,老生代存放生存时间长的对象
新生代 | 老生代 |
---|---|
存放生存时间短的对象 | 存放生存时间长的对象 |
容量小,只支持1~8M容量 | 容量大 |
副垃圾回收器实现回收 | 主垃圾回收器实现回收 |
不管是副垃圾回收器还是主垃圾回收器都遵循这相同的执行流程
- 标记空间中活动对象和非活动对象,活动对象就是还在使用的对象,非活动对象就只要清除的对象
- 回收非活动对象占用的内存
- 做内存整理,因为回收对象后,内存中会出现大量不连续的空间,这样的空间称为内存碎片,当需要分配大容量空间时,就有可能出现内存溢出的情况。
副垃圾回收器
新生代中通常情况下存放的都是小体积的对象,因此空间不大,垃圾回收较为频繁,使用副垃圾回收器来回收垃圾。新生代中使用Scavenge算法来处理,将新生代划分成了对象区域和空闲区域,新加入的对象会先存放到对象区域,待对象区域中写满时,执行一次垃圾回收操作。此时副垃圾回收器先标记对象区域中的活动对象和非活动对象,然后将活动对象复制到空闲区域,并有序的排列,避免出现内存碎片。完成复制后,清空之前对象区域里的非活动对象,然后对象区域与空闲区域角色互换,这样就完成了一次垃圾清除。
因为这种复制需耗费时间,因此新生代的空间不会设置的太大,以免影响执行效率。
如果经历了两次垃圾回收还存活的对象,就会被移动到老生代区域,这也是为节省新生代的空间,这个现象就叫对象晋升策略。
主垃圾回收器
老生代的空间较大,除了存放比较大的对象外,还有从新生代晋升的对象,所以主垃圾回收器不使用Scavenge算法进行垃圾回收,因为复制这些大的对象会花费更多的时间,导致回收的效率不高。
主垃圾回收器采用标记-清除(Mark-Sweep)算法来进行垃圾回收,首先标记阶段,会遍历调用栈,如果找到了对堆中对象的引用地址,则将这个对象标记为活动元素,否则为非活动对象,也就是垃圾数据。遍历完成后就开始垃圾的清理,这个过程就是清除非活动对象的过程。
4.查看程序内存使用情况
通过chrome开发者工具的perfomance