页面堆内存调试
查看内存使用
我们可以通过Chrome Task Manager查看tab页使用的内存
它显示的内存有两类
- JavaScript Heap Memory,页面运行过程中JavaScript(V8)使用的堆内存,它包含两个值:
- 总值,例如这个4656K,它不在圆括号中,这是总heap memory
- 实际可访问值,表示页面中可访问的对象的内存大小,它在圆括号中,当新对象创建或现有对象内容增长时可以观察到他在增加
- renderer总内存,Blink(renderer)渲染页面也会占用内存,这是这个renderer在操作系统级别的总内存使用量,包含这个tab页(renderer)的一切,关于renderer有什么,见 Blink 架构
这个页面中,它的内存占用空间为88.0MB,在macOS的活动监视器中也可以看到这个renderer进程的总内存为88.0MB。
手动GC
可以通过Chrome DevTools中的GC按钮触发一次强制GC。
手动GC后可以看到JavaScript的实际可访问值有所减少。
实时查看
在 Performance Monitor 中可以查看页面实时的内存、DOM节点数量。
JavaScript 堆内存调试
一个页面即使没有使用任何JavaScript,页面也会有堆内存占用,因为v8在blink主要有两个使用方式:
- v8 - 执行JavaScript
- blink binding - 浏览器除了执行JavaScript,还有Window、DOM等全局对象,这些由blink负责binding至V8::Context中
这些页面的默认JavaScript始终会占据一部分JavaScript堆内存。
堆内存快照
通过Chrome Dev Tools - Memory提供的堆内存快照功能我们可以查看页面当前的JavaScript堆内存使用情况。在Chrome隐身窗口拍一个快照看看一个空页面堆内存中都有什么东西,注意要使用隐身窗口,因为Chrome扩展跟页面同属一个V8::Isolate。
默认情况下Memory面板根据对象构造器分类,可以看到Summary有4列:
- Constructor - 对象的构造器
- Distance - 这个对象距Window对象的 “距离”
- Shallow Size - 这个节点自身的尺寸(bytes)
- Retained Size - 这个节点持有的尺寸,意思是被这个节点所引用的对象的尺寸。例如对象A持有对象B(即通过A某种方式引用B),那么A被回收之前B都不能被回收,那么A的Retained Size就是B的尺寸。
新建一个Class,并创建两个它的实例看看它在堆内存快照中是什么样
在Class filter中输入Test来找到这个构造器,在被点击的Test节点下方可以看到Test实例有两个属性,分别为name与age,Test实例的Shallow Size与Retained Size相同,说明这个实例只持有自身。
Test@74823
表示这个实例的内存标记为@74823,其他的类似。
接下来看看Retainers,这是所有引用此节点的节点树。点击name节点
可以看到 name 在 Test@74385上(即t2),t2在 system / Context @74795上,依此类推直到 native_context。