目录
背景
拍摄堆快照
一个真实世界的例子——AsyncSubject
附加说明
兴趣点
- 下载源 - 1.2 KB
当您关闭浏览器选项卡时,所有内存都将被释放。内存泄漏在Web浏览器上很可能不是大问题。但是如果你有一个长时间运行的应用程序,它可能是一个问题。这是关于如何检测Web浏览器上的内存泄漏的说明。在本说明中,我将使用示例来展示如何在开发工具上使用内存功能。我注意到Chrome和Edge上的开发工具是最容易使用的。
拍摄堆快照在Chrome或Edge开发工具中,我们可以采用三种内存配置文件。
在这篇笔记中,我将重点关注“堆快照”,它非常有效地精确定位导致内存泄漏的对象。测试HTML页面如下:
button {
height: 60px;
border-radius: 5px;
font-weight: 800;
background-color: aquamarine;
}
Memory test - first attempt
let MTestClassesArray = [];
class MTestClass {
constructor() {}
}
const create_1000_objects = () => {
for(let i = 0; i < 1000; i++) {
MTestClassesArray.push(new MTestClass());
}
const text = `Total ${MTestClassesArray.length} `
+ `MTestClass objects created`;
document.getElementById('divMsg').innerHTML = text;
};
Create 1000 MTestClass objects
- 在这个HTML页面中,我们有一个按钮。
- 每次单击按钮,都会创建1000个“MTestClass”类型的对象。
- 每个对象都插入到数组“ MTestClassesArray”中。
- 由于数组“MTestClassesArray”是在全局范围内声明的,因此对象不再是可垃圾回收的。
为了验证上述陈述,让我们加载页面并单击几次按钮。在我的实验中,我使用了Edge。
正如页面中所示,我已单击该按钮3次,并创建了3000 个“MTestClass”对象。我们可以通过“CTRL+SHIFT+i”调出开发工具。在获取内存快照之前,让我们首先强制进行垃圾回收。
然后我们可以在垃圾收集之后拍摄内存快照。
内存快照使我们能够很好地了解内存堆。
- 我们可以过滤快照以检查某些类类型的对象是否在内存堆中。在我们的示例中,我们可以看到正好3000个“ MTestClass”对象。
- 我们还可以看到是什么对象阻止了“ MTestClass”对象被垃圾收集。在我们的示例中,它是“MTestClassesArray”对象。
开发工具甚至可以告诉我们哪一行代码创建了“MTestClass”对象。
如果您订阅了一个事件,则需要取消订阅它。如果没有,很可能是内存泄漏。但是rxjs中的 "AsyncSubject"是这样吗?
button {
height: 60px;
border-radius: 5px;
font-weight: 800;
background-color: aquamarine;
}
Memory test - async subject
const get_time = () => {
const element = document.getElementById('divTime');
const subject = new rxjs.AsyncSubject();
element.innerHTML = '';
setTimeout(() => {
subject.next(new Date());
subject.complete();
}, 3 * 1000);
subject.subscribe((data) => {
element.innerHTML = data.toString();
});
};
Get Time by AsyncSubject
- 在这个HTML页面中,我们有一个按钮。
- 点击按钮,页面上会显示当前时间。
- 我没有直接获取时间,而是创建了一个“AsyncSubject”,时间是在定时器回调函数中获取的。
- 然后程序订阅“AsyncSubject”并将其显示在页面上。
需要注意的是,“AsyncSubject”是在“get_time”箭头函数中创建的,因此与任何全局上下文无关。我将假设它在计时器回调之后是可垃圾回收的。但是让我们确认它正在使用开发工具。
单击按钮和显示时间之间有3秒的延迟。为了确认“AsyncSubject”是可垃圾回收的,让我们拍两个堆快照。一个在定时器回调之前,一个在定时器回调之后。
在定时器回调之前,我们可以在内存堆中找到“AsyncSubject”。此时,它不是垃圾回收的,因为它被一些其他资源保留并且最终可以从window对象访问。
但是在定时器回调之后,AsyncSubject收集了“ ”。如果没有收集,您可以手动强制收集。通过这个例子,我们可以对我们的程序更有信心。如果“ AsyncSubject”使用正确,我们不需要取消订阅该事件。
附加说明- 已经注意到,如果你曾经“console.log()”一个对象,它就不再是可垃圾回收的。在生产版本中,如果您有内存问题,您应该记住这一点。
- 在堆快照中搜索对象时,如果您的程序被缩小,则可以通过缩小器更改类的名称。
- 这是关于如何检测Web浏览器上的内存泄漏的说明。
- 开发工具对于我们了解内存堆非常有用。
- 我希望你喜欢我的文章,我希望这篇笔记能以一种或另一种方式帮助你。
Detect Memory Leak on Web Browsers - CodeProject