提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
JS 语言不像 C/C++, 让程序员自己去开辟或者释放内存,而是类似Java,采用自己的一套垃圾回收算法进行自动的内存管理。作为一名前端工程师,对于JS内存回收的机制是需要非常清楚, 以便于在极端的环境下能够分析出系统性能的瓶颈,另一方面,学习这其中的机制,也对我们深入理解JS的闭包特性、以及对内存的高效使用,都有很大的帮助。
提示:以下是本篇文章正文内容,下面案例可供参考
一、V8内存限制
默认情况下,64位下1.4g,32位下0.7g(可以自行设置)
有小伙伴就问了,电脑这么大的内存,为什么不多分配一些?
原因就是,因为js是单线程机制,每次进入到垃圾回收阶段,其他业务逻辑都要暂停,而且垃圾回收是非常耗时的操作。
按官方的说法,以 1.5 GB 的垃圾回收堆内存为例,V8 做一次小的垃圾回收需要 50 毫秒以上,所以说,内存不是越大越好
(想想平时页面稍微一点点卡,就暴躁了。。。👺👺👺)
二、内存分代
1.根据存活时间,内存分为新生代和老生代
新生代:由from和to两部分组成
from 为正在使用的内存,to为闲置内存
默认情况下,内存大小为
64位:from和to各占16M,32位:from和to各占8M
老生代
64位:占1400M 32位:占700M
2.垃圾回收机制
2.1 新生代的内存回收
先将from里的对象检查一遍,如果对象存活,则复制到to中
(按顺序排放),将非存活对象进行回收,当所有存活对象进入to中,然后交换from和to
,from变为闲置内存,to变为正在使用内存
如果一个对象经过多次交换依然存在
或者新的数据太大
,则将其放置在老生代中
2.2老生代的内存回收
2.2.1 标记清除
在这个阶段分为标记阶段
和清除阶段
,首先会遍历堆中的所有对象,并做上标记,对于那些在代码环境中使用的变量
和强引用的变量
进行取消标记
剩下被标记的变量就是需要被回收的变量,在随后的清除阶段进行回收
2.2.2 标记整理
在清除阶段完成后,由于是在堆里清除,所以清除完后会产生内存碎片问题,存活对象的空间不连续导致对后续分配空间造成障碍,所以需要整理碎片:将存活的对象全部往一边靠拢
,由于是移动对象,它的执行速度不可能很快,事实上也是整个过程中最耗时间的部分
。
2.2.3 优化— 增量标记
由于JS的单线程机制,V8 在进行垃圾回收的时候,不可避免地会阻塞业务逻辑的执行,倘若老生代的垃圾回收任务很重,那么耗时会非常可怕,严重影响应用的性能。那这个时候为了避免这样问题,V8 采取了增量标记的方案。
将标记任务分为许多小任务,在执行完一个小任务后,让js的逻辑代码执行一会儿,然后再执行下一个小任务。
经过增量标记之后,垃圾回收机制对js的阻塞时间降低至原来的1/6
总结
JS垃圾回收的原理就介绍到这里了,其实理解起来是非常简单的,重要的是理解它为什么要这么做,而不仅仅是如何做的,希望这篇总结能够对你有所启发。