Z

页面堆内存调试

查看内存使用

我们可以通过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,并创建两个它的实例看看它在堆内存快照中是什么样

1class Test {
2    name = "foo"
3    age = 12
4}
5const t1 = new Test();
6const t2 = new Test();

在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。