欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【JS档案揭秘】第一集 内存泄漏与垃圾回收

程序员文章站 2022-11-08 14:46:51
程序的运行需要内存,对于一些需要持续运行很久的程序,尤其是服务器进程,如果不及时释放掉不再需要的内存,就会导致内存堆中的占用持续走高,最终可能导致程序崩溃。 不再需要使用的内存,却一直占用着空间,得不到释放,这就叫内存泄漏。 在JS中,我们都知道,基本数据类型是存在栈(stack)中,而引用数据类型 ......

程序的运行需要内存,对于一些需要持续运行很久的程序,尤其是服务器进程,如果不及时释放掉不再需要的内存,就会导致内存堆中的占用持续走高,最终可能导致程序崩溃。

不再需要使用的内存,却一直占用着空间,得不到释放,这就叫内存泄漏

在js中,我们都知道,基本数据类型是存在栈(stack)中,而引用数据类型是存在堆(heap)中。存在栈中的数据,会被自动处理掉。但存在堆中的数据则不然。

js引擎有个垃圾回收机制,可以帮助我们来清除不需要的数据。关键来了,我们怎么告诉js引擎这个我不再需要这个数据呢?

答案就是:切断它的引用,让它变成一座无法到达的岛屿

这就是所谓的“标记清除”。也就是说,我们对堆中的引用类型数据做一个遍历,标记一下它们是否是可以被外部访问到的:

let a = {name:'zhang'};
let b = a;

let c = {name:'zhao'};
c = null;

在上面的这段代码中,{name:'zhang'}这个对象分别被变量a和变量b引用。{name:'zhao'}这个对象一开始被变量c引用,后来c被重新赋值,{name:'zhao'}这个对象的引用突然被切断,再也无法被访问到了,自己变成了一个“孤岛式数据”,无法被外部访问,被当成了垃圾。

【JS档案揭秘】第一集 内存泄漏与垃圾回收

 

而垃圾的宿命,就是被js引擎回收。

【JS档案揭秘】第一集 内存泄漏与垃圾回收

我们来执行一下上述这段代码,每点击一次,就给obj存入1000个不同对象的引用,连续点击10s,停止30s。并把这个过程录制下来。

怎么录?打开chrome的performance即可录制,看看这40s的内存堆(js heap)的走势。

【JS档案揭秘】第一集 内存泄漏与垃圾回收

 

 (结果是令人寒心的,堆内存占用从15m左右飙到最高30m,且基本没有什么回落,居高不下)

 

现在我们把代码改一改,在末尾增加一句this.obj = []。用于清除本次操作产生的1000个引用。

【JS档案揭秘】第一集 内存泄漏与垃圾回收

按照同样的手法,点击10s,停止30s,总共录制40s。效果如下:

【JS档案揭秘】第一集 内存泄漏与垃圾回收

(可以看到中途最高飙到24.7m,但是垃圾回收在第5s和第10s都介入了一次,使得内存占用大幅减少)

 

可以看到垃圾回收还是很有用的,同时也可以看到,垃圾回收并不是无时无刻都在进行,因为垃圾回收这个操作也有性能损耗,从我实测的结果来看,它是按照一定的时间间隔进行的。