v8引擎内存结构
- 内存分配:栈空间,堆空间
- 栈空间:代码运行的环境(逻辑运行的环境
- 堆空间:所有函数和引用类型数据存放的具体地址
- 堆空间有哪些部分:
1. New Space(Young generation)新生代,
新生代内存大小为:
新生代会将内存完全平分为两个部分:
Semi space from, Semi space to
2. Old Space(Old Generation) 老生代,
3. Large object space 大对象内存空间(对象超过默认大小限制时,塞入Large object space,并且不受GC垃圾回收机制管理)
4. Code space(即时编译器会把我们已经编译的代码存在Code Space,随时在栈中执行)
5. Cell space (单元空间)
6. Property cell space (属性单元空间)
7. Map space (地图空间)
- 新生代和老生代内存大小
内存跟操作系统有关,64位还是32位
64位:新生代空间为64MB,老生代空间为1400MB
32位:新生代空间为32MB,老生代空间为700MB
补充:
1.v8引擎64位总大小为1.4G(1464MB),32位为0.7G(732MB)
2.node(v14之后),v8引擎内存为2GB
- 垃圾回收算法
1. 新生代有一种算法
思想:Copy(复制)
特点:短频快
Scavenge算法:新生代互换
运行步骤:当定义了变量,首先放到新生代(Semi space from)中,因为新生代64M一分为二,只有32M,当达到条件后,会标记Semi sapce from里的变量,判断是否被引用,然后标记是否要被清除,把不需要清除所有内容复制到(Semi space to)空间。 然后将Semi space to 空间与Semi space from互换,情况原来的Semi space from 空间。
ps:为什么要复制,因为牺牲空间来换时间。
2. 老生代有两种算法组合起来
思想:三步走(标记,整理,清除)
Mark-Sweep方法(标记清除)
Mark-Compact方法(标记整理)
运行步骤:
ps:老生代为什么不用复制,因为老生代内存有1400M,如果用Scavenge算法,那么内存需要一分为二,因为着,有700M的内存常常处于闲置状态。
- 标记清除法
任何引擎,都有垃圾回收机制的跟节点(GC Roots),类似于js主线程的window。
扫描引用关系,被扫描到的变量和对象就会给予标记,被标记的内容就是有用的数据,没有扫描到的就是垃圾。
1. 广度扫描
2. 全停顿标记
3. 增量标记法 & 三色标记法
4. 引用计数
ps: 标记整理法就是在标记清除法的基础上进行整理,把非垃圾数据进行整理,整理成连续的不间断的结构,然后清除。(标记-整理-清除)
- 增量标记法
-
三色标记法
-
内存需求
首先了解v8引擎最大内存为2GB
1. 大文件上传
如果大小超过2GB,服务直接宕掉
2. webpack打包内
3. vite(多项目集群)
- 为什么v8引擎内存最大才2G
1. 前端的不持久化,一般情况下执行完就会被回收
2. js是单线程运行的 (如果进入垃圾回收,所有的运行逻辑都会暂停 )
3. 垃圾回收机制限制(官方文档中,回收1.5G内存需要时间50ms )
- 垃圾回收实例
function test() {
debugger
var a = 1 // 基本数据类型
var b = {} // 引用数据类型
var c = { a: a } // 引用数据类型
return c
// 如果返回基本类型 例如:return 'ok', 那么直接被回收
// 基本类型如果用参数获取返回数据,那么相当于简单复制
// 引用数据类型如果用参数获取返回数据,相当于获得堆内存地址,最终指向的还是变量c内存地址
}
// 情况1
test()
// 情况2
var itest = test()
// 执行完test后,c的内存会被回收吗
// 情况1 只是用了test方法,会被回收
// 情况2 如果用变量接收,就不会被回收(闭包)
/**
* 运行过程
* 1. 匿名作用域
* 2. test()入栈
* 3. 创建a变量(栈中)
* 4. 创建b变量(栈中,堆中会开辟一个内存地址0x111)
* 5. 创建c变量(栈中,堆中会开辟一个内存地址0x111)
* */
- 为什么要关注内存
1.防止页面占用内存过大,引起客户端卡顿,甚至无响应。
2.Node使用的也是v8,内存对于后端服务的性能至关重要,因为服务的持久性,后端更容易造成内存溢出
ps:v8引擎的标记一直在进行,但是清除,只有在内存满了,或者达到某个条件,GC垃圾回收机制才会介入。
网友评论