当前位置:网站首页>js 内存泄漏
js 内存泄漏
2022-06-11 02:10:00 【神奇大叔】
内存泄漏:当不再用到的对象内存,没有及时被回收,想要避免就让无用数据不存在引用关系。
内存膨胀:即在短时间内内存占用极速上升到达一个峰值,想要避免需要使用技术手段减少对内存的占用。
频繁GC: GC执行的特别频繁,一般出现在频繁使用大的临时变量导致新生代空间被装满的速度极快,而每次新生代装满时就会触发 GC,频繁 GC 同样会导致页面卡顿,想要避免的话就不要搞太多的临时变量,因为临时变量不用了就会被回收。
泄漏1:闭包
- 有权访问另一个函数作用域中的变量的函数
泄漏2:隐式全局变量
- 函数中的局部变量在函数执行结束后这些变量已经不再被需要,所以垃圾回收器会识别并释放它们。但是对于全局变量,垃圾回收器很难判断这些变量什么时候才不被需要,所以全局变量通常不会被回收
function fn(){
// 没有声明从而制造了隐式全局变量test1
test1 = new Array(1000).fill('isboyjc1')
// 函数内部this指向window,制造了隐式全局变量test2
this.test2 = new Array(1000).fill('isboyjc2')
}
fn()
- 因为没有声明和函数中this的问题造成了两个额外的隐式全局变量,这两个变量不会被回收
泄漏3:DOM引用
<div id="root">
<ul id="ul">
<li></li>
<li></li>
<li id="li3"></li>
<li></li>
</ul>
</div>
<script>
let root = document.querySelector('#root')
let ul = document.querySelector('#ul')
let li3 = document.querySelector('#li3')
// 由于ul变量存在,整个ul及其子元素都不能GC
root.removeChild(ul)
// 虽置空了ul变量,但由于li3变量引用ul的子节点,所以ul元素依然不能被GC
ul = null
// 已无变量引用,此时可以GC
li3 = null
</script>

泄漏4:定时器
- 当不需要 interval 或者 timeout 时,最好调用 clearInterval 或者 clearTimeout来清除,另外,浏览器中的 requestAnimationFrame 也存在这个问题,我们需要在不需要的时候用 cancelAnimationFrame API 来取消使用
泄漏5:事件监听
<template>
<div></div>
</template>
<script>
export default {
created() {
window.addEventListener("resize", this.doSomething)
},
beforeDestroy(){
window.removeEventListener("resize", this.doSomething)
},
methods: {
doSomething() {
// do something
}
}
}
</script>
泄漏6:事件的监听发布
<template>
<div></div>
</template>
<script>
export default {
created() {
eventBus.on("test", this.doSomething)
},
beforeDestroy(){
eventBus.off("test", this.doSomething)
},
methods: {
doSomething() {
// do something
}
}
}
</script>
- 当实现了监听者模式并收集了相关的事件处理函数,其中引用的变量或者函数都被认为是需要的而不会进行回收
泄漏7:Map、Set强引用
let obj = {
id: 1}
let user = {
info: obj}
let set = new Set([obj])
let map = new Map([[obj, 'hahaha']])
// 重写obj
obj = null
//以下强引用,并不会因为垃圾回收掉
console.log(user.info) // {id: 1}
console.log(set)
console.log(map)
map.delete(obj);
obj = null; //此时才能去除map对key所引用对象的强引用
let weakSet = new WeakSet([obj])
let weakMap = new WeakMap([[obj, 'hahaha']])
// 重写obj引用
obj = null
// {id: 1} 将在下一次 GC 中从内存中删除
泄露8:未清理的console
- 之所以在控制台能看到数据输出,是因为浏览器保存了我们输出对象的信息数据引用,也正是因此未清理的 console 如果输出了对象也会造成内存泄漏
内存泄漏定位
- 先点击6手动进行一次垃圾回收,4、5都点上,然后点击1开始录制

- 可以看到快照对应下的内存曲线,如果在手动执行垃圾回收后,曲线并没有明显下降,说明可能存在内存泄漏
- 点击Memory,可以为我们提供更多详细信息,比如记录 JS CPU 执行时间细节、显示 JS 对象和相关的DOM节点的内存消耗、记录内存的分配细节等
- 其中的 Heap Profiling 可以记录当前的堆内存 heap 的快照,并生成对象的描述文件,该描述文件给出了当下 JS 运行所用的所有对象,以及这些对象所占用的内存大小、引用的层级关系等等,用它就可以定位出引起问题的具体原因以及位置。

- 先手动点击垃圾回收,然后操作页面,然后点击1生成快照,循环操作几次

Summary:按照构造函数进行分组,捕获对象和其使用内存的情况,可理解为一个内存摘要,用于跟踪定位DOM节点的内存泄漏
Comparison:对比某个操作前后的内存快照区别,分析操作前后内存释放情况等,便于确认内存是否存在泄漏及造成原因
Containment:探测堆的具体内容,提供一个视图来查看对象结构,有助分析对象引用情况,可分析闭包及更深层次的对象分析
Statistics:统计视图

Constructor:显示所有的构造函数,点击每一个构造函数可以查看由该构造函数创建的所有对象
Distance:显示通过最短的节点路径到根节点的距离,引用层级
Shallow Size:显示对象所占内存,不包含内部引用的其他对象所占的内存
Retained Size:显示对象所占的总内存,包含内部引用的其他对象所占的内存
//Constructor这一列
system、system/Context 表示引擎自己创建的以及上下文创建的一些引用,这些不用太关注,不重要
closure 表示一些函数闭包中的对象引用
array、string、number、regexp 这一系列也能看出,就是引用了数组、字符串、数字或正则表达式的对象类型
HTMLDivElement、HTMLAnchorElement、DocumentFragment等等这些其实就是你的代码中对元素的引用或者指定的 DOM 对象引用
- 选择Comparison比较,或者右侧的filter


New:新建了多少个对象
Deleted:回收了多少个对象
Delta:新建的对象数 减去 回收的对象数
- 需要重点关注 Delta ,只要它是正数就可能存在问题

- closure 上面也说过代表闭包引用,可以查看到代码中发生引用的位置
- 根据其他的如Array等构造函数的Distance层级也能定位发生泄漏的位置
- 如上就能定位两个问题,一是代码 30 行的闭包引用数组造成的内存泄漏,二是数组的元素不断增多造成的内存泄漏。
边栏推荐
- Three special data types, day3 and redis (geographic location, cardinality statistics and bitmap scene usage)
- 当逻辑删除遇上唯一索引,遇到的问题和解决方案?
- mysql重装时写my.ini配置文件出错
- List 过滤、排序、校验等处理方法
- 弄懂了采矿业与碳中和的逻辑,就读懂了矿区无人驾驶的千亿市场
- AOSP ~ 修改WebView默认实现
- Kotlin apply方法
- MOFs, metal organic framework materials of folic acid ligands, are loaded with small molecule drugs such as 5-fluorouracil, sidabelamine, taxol, doxorubicin, daunorubicin, ibuprofen, camptothecin, cur
- One line of code solves the problem that the time to fetch datetime from MySQL database is less than eight hours
- Unity animator rewind
猜你喜欢

MySQL backup and recovery

CPT 102_LEC 15

【新晋开源项目】动态配置化任务编排框架 Gobrs-Async 加入Dromara开源社区

CPT 102_LEC 17

MOFs, metal organic framework materials of folic acid ligands, are loaded with small molecule drugs such as 5-fluorouracil, sidabelamine, taxol, doxorubicin, daunorubicin, ibuprofen, camptothecin, cur

牛客网:数组中只出现一次的两个数字

Flat data to tree and tree data flattening

【斐波那契数列】

Everything实现快速搜索的原理

叶酸配体的金属有机骨架材料MOFs负载5-氟尿嘧啶,西达本胺,紫杉醇,阿霉素,柔红霉素,布洛芬,喜树碱,姜黄素,藤黄酸等小分子药物
随机推荐
Stc8a8k64d4 EEPROM read / write failure
Core principle and code explanation of epoll reactor model
AOSP ~ WIFI默认开启 + GPS默认关闭 + 蓝牙默认关闭 + 旋转屏幕关闭
Explanation of spark common parameters
Three special data types, day3 and redis (geographic location, cardinality statistics and bitmap scene usage)
What do you know about the set class? Soul questions from Volume I
[implementation of bubble sorting]
Project load failed
GCC C内联汇编
To view the data in redis, in addition to the command line and client, you have a third option
基于互联网架构演进, 构建秒杀系统
靠贴牌飞利浦冲击上市,德尔玛的自有品牌又该如何“起跳”?
Unity determines whether the object is in the camera field of view
逃离大城市的年轻人:扛住了房价和压力,没扛住流行病
CPT 102_LEC 16
net core天马行空系列-可用于依赖注入的,数据库表和c#实体类互相转换的接口实现
[untitled]
When a logical deletion encounters a unique index, what are the problems and solutions?
Use of CIN and cout
【189. 轮转数组】