持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情 如果你嫌前面啰嗦,可以直接根据大纲跳转~
前言
前段时间写了 页面内存泄露 到底是啥?谁搞的?问到哪些情况出现能答上来吗,在最后留了一下本文的坑~、
你能学到🍗
node.js
如果是 node 环境下,
我们可以使用 Node 提供的process.memoryUsage方法。process.memoryUsage
返回一个对象,包含了 Node 进程的内存占用信息。该对象包含五个字段
- rss (resident set size):所有内存占用,包括指令区和堆栈。
- heapTotal:”堆”占用的内存,包括用到的和没用到的。
- heapUsed:用到的堆的部分。
- external:V8 引擎内部的 C++ 对象占用的内存。
- arrayBuffers:分配给ArrayBuffers和SharedArrayBuffers的内存,包括所有Node.js的Buffers。
单位是字节
判断内存泄漏主要用heapUsed
,而这个方法主要是在Node
环境下,所以我们这里不做实操了
除了命令行,我们还可以利用 开发者工具~(本文主要讲这个,实操也只有这个~)
先了解一下 Chrome devtool🔨
很多人应该还没怎么用过开发者工具做这些东西,这里先将一下相关的按钮和图形代表的意思,在后面实操会带着具体操作~
性能 Performance🚀
f12
打开开发者工具,选择性能(Performance
)
当你想进行测量时,点击录制,然后进行操作正常的页面点击等操作就行了,配合手动垃圾回收,最后结束录制查看内存情况就好了
内存 Memory🍱
时间轴上的分配插桩
当你想进行测量时,点击录制,然后进行操作正常的页面点击等操作就行了,就可以看到一些柱子,有蓝色有灰色,蓝色的可能会变成灰色。
- 蓝色表示当前占用着的内存
-
堆快照
前面的都只是查看是否有内存泄漏,这个可以抓取两份快照,查看占用内存的对象到底是啥,然后我们可以借助这些信息来抓住可恶的内存小偷。
具体使用看下面的实操环节~demo 准备😛
先准备一下肯定会出现内存泄漏的场景,就用 不当的 console.log 做例子吧
index.html
<div id="root">
<button>button</button>
</div>
<script src="./index.js"></script>
index.js
document.querySelector("button").addEventListener("click", function () {
let big = new Array(999999);
// console.log(big);
});
实操🪐
性能
操作
我们打开
index.html
, 打开开发者工具-性能
- 点击录制
- 先手动垃圾回收一下清空初始值
- 接着点击三下 button
- 接着手动垃圾回收一下试试
- 最后结束录制
效果
可以看到我们点击三次 button,JS 堆
阶梯上升,并且最后手动内存回收后仍然存在。这正是因为点击事件中创建的数组都被console.log
保存了下来导致无法回收
注释掉的效果
document.querySelector("button").addEventListener("click", function () {
let big = new Array(999999);
//console.log(big); // 把这行代码注释掉
});
你可以将console.log
注释掉,之后进行和上面一样的操作,再看看效果
可以看到每次new Array
之后,会先将之前的内存销毁,并且最后手动垃圾回收之后,内存占用与初始值相比基本平稳,也就是说没有内存泄漏了~
内存分配插桩
操作
效果
可以看见每次点击按钮都会出现一个蓝色柱子,并且不会变灰。也就是出现了被占用的内存但是不会被回收掉
注释掉的效果
还是和上面操作一样,将console.log
语句注释掉
可以看见出现蓝色柱子后(除了初始的那一条)很快就会变为灰色,说明之前的内存已经被清除释放~
内存堆快照
我们一开始先什么都不操作录制一份堆快照,然后再点击三次再录制一分堆快照。
现在就得到了堆快照1
和堆快照2
比较
然后我们选择与快照1比较对比内存分配,按照大小从大到小排序
可以看见罪魁祸首是数组
控制
再到控制里看一下,大小从大到小排序
可以看见确实是console.log
的锅~
GC 就是 Garbage Collector),垃圾回收,GC root 就是垃圾回收器的对象
总结
是否有案情(是否有内存泄漏)🤔
当然,这里 demo 例子比较简单,所以能比较轻松地查看内存泄漏清空。
实际上,这些工具能看见的内容相对与代码直接报错等排查会少得多,或者说“难看”得多。
这些工具大部分时候都是没法直接给你答案,告诉你谁是元凶。(不然他们为啥不直接warning
或者error
呢)
他只能提供部分内存信息,可能会告诉你哪些是嫌疑犯,甚至大部分时候这些信息都很难找,因为有时会嵌套地很深
而你需要靠这些信息和自己写代码的经验来排查凶手~
预防
其实排查内存泄漏真的是挺麻烦的~ 所以写代码的时候一定要注意啊,如果你还不太了解出现内存泄漏的场景,可以看看下面的推荐阅读~