NodeJs - Chrome内存分析工具使用
- [一. 前期准备](#一. 前期准备)
- [二. Chrome 内存分析工具使用](#二. Chrome 内存分析工具使用)
-
- [2.1 查看快照](#2.1 查看快照)
- [2.2 使用案例](#2.2 使用案例)
一. 前期准备
我们下载好相关依赖:
java
npm i v8-profiler-next
测试代码:
java
const v8Profiler = require('v8-profiler-next')
const fs = require('fs')
function createArray () {
const arr = [];
for (let i = 0; i < 100000; i++) {
arr.push({ index: i, value: `value-${i}` });
}
return arr;
}
let leakArr = [];
function run () {
createArray();
createArray();
createArray();
console.log('Arrays created');
setInterval(() => {
console.log('Interval');
// 模拟内存泄漏,将一个对象添加到数组中
for (let i = 0; i < 100000; i++) {
leakArr.push({ index: i, value: `value-${i}` });
}
}, 1000);
}
run();
const snapshot = v8Profiler.takeSnapshot();
snapshot.export((err, result) => {
fs.promises.writeFile(`${Date.now()}.heapsnapshot`, result);
snapshot.delete()
})
setInterval(() => {
const snapshot = v8Profiler.takeSnapshot();
snapshot.export((err, result) => {
fs.promises.writeFile(`${Date.now()}.heapsnapshot`, result);
snapshot.delete()
})
}, 10000);
运行之后,当前目录会生成下面多个snapshot
文件(运行时间久一点,15秒左右就可以):
二. Chrome 内存分析工具使用
Chrome内存分析工具中,对于视图的查看分为4种:
2.1 查看快照
快照的查看种类还有:
Summary
视图:会显示按构造函数名称分组的对象。使用它可以根据按构造函数名称分组的类型找出对象(及其内存用量)。它对于跟踪DOM
泄露特别有用。- 比较视图(重点):会显示两个快照之间的差异。可使用它来比较操作前后的两个(或更多)内存快照。通过检查已释放内存中的增量和引用计数,您可以确认是否存在内存泄漏及其原因。
- 包含视图 :允许探索堆内容。它可让您更好地查看对象结构,有助于分析全局命名空间 (
window
) 中引用的对象,从而找出导致其存在的原因。您可以使用它分析闭包并在较低级别深入了解您的对象。 - 支配项视图:会显示支配项树,可用于查找累积点。 此视图有助于确认是否有对对象的意外引用仍然保留,以及删除/垃圾回收是否确实在正常运行。
2.2 使用案例
浏览器输入:chrome://inspect/#devices
,如图,点击Open dedicated DevTools for Node
:
点击之后出现相关弹框,我们点击加载按钮,把我们生成的两个dump
文件加载进去:
加载好后,如图:
一般内存泄漏,我们重点关注是否存在:只有新增对象,却没有删除项的类别。 如图:
这里我们看到Object
对象几乎都是新增,新增了一百万个,那么几乎可以确认这些对象就是内存泄漏的点了,我们展开来看下它的内容有啥:
就是我们循环里面不停地给数组中增加的对象:
因为这个数组,它在setInterval
这个函数中被引用,所以它永远不会被释放,从而模拟出内存泄漏甚至最终OOM
的情形。
相关名词解释:
Constructor
:构造函数,表示使用此构造函数创建的所有对象。#New
:表示在两个快照之间新创建的对象数量。这些对象在两个快照之间被分配了内存。#Deleted
:表示在两个快照之间被删除的对象数量。这些对象在两个快照之间释放了内存。#Delta
:表示在两个快照之间的内存变化量。它是新创建对象的内存减去已删除对象的内存。Distance
:表示对象与根对象之间的距离。根对象是内存中的起点,而距离是指从根对象到特定对象的路径长度。较大的距离值表示对象与根对象之间的引用链更长。Shallow Size
:表示对象本身占用的内存大小 ,不包括对象引用的其他对象的内存。Retained Size
:表示对象及其所有可达对象占用的内存大小 。它包括对象本身的内存大小以及对象引用的其他对象的内存大小。
Alloc Size:表示对象在内存中分配的总大小,包括对象本身的大小以及对象引用的其他对象的大小。这个值是对象在内存中实际占用的大小。Freed Size
:表示在两个快照之间释放的对象的总大小。这些对象在两个快照之间被删除或释放了内存。Self Size
:表示对象本身占用的内存大小,不包括对象引用的其他对象的内存。与Shallow Size
类似,但Self Size
更常用于表示对象的实际占用大小。Retainers
:表示引用特定对象的其他对象的数量。这些对象保持对特定对象的引用,因此会阻止特定对象被垃圾回收。