业务仔就写好业务,内存泄漏不是你该关心的问题

简介: 业务仔就写好业务,内存泄漏不是你该关心的问题

老是听到有人说内存泄漏,但是我做开发这么多年,除非我故意去测试内存是怎么泄漏的,这个时候才会内存泄漏,其他情况下几乎没有遇到过内存泄漏的问题。


然后就一直思考我没遇到内存泄漏的问题是不是跟我做的业务体量太小有关系?带着问题去找答案,今天就来聊聊内存泄漏。


什么是内存泄漏


内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。


在我们最常听到的就是闭包没用好就容易造成内存泄漏,然而因为闭包产生的内存泄漏其实是很少的,因为内存泄漏的原因很多;


通常产生内存泄漏的原因有:


  • 闭包
  • 循环引用
  • DOM引用
  • 定时器
  • 事件监听
  • 作用域未释放
  • 递归调用
  • 全局变量
  • 未清理的大对象
  • 其他各种原因导致内存未释放的情况


在这里我就不一一介绍了,上面这么多种情况其实在JQuery支配的时代,造成内存泄漏的原因有两个,一个是DOM引用,一个是全局变量


因为JQuery的时代想要用单页面应用,切换页面的时候就会销毁一部分DOM,但是这个时候很多人会忘记把DOM的引用清除掉,导致DOM一直存在内存中,这就是DOM引用造成的内存泄漏;


还有一个就是全局变量,当时的单页面跨页面通信都是通过全局变量来实现的;


除了跨页面通讯还有开发人员的编码习惯,直接在js文件中的最顶层使用var来定义变量,或者是直接不使用var来定义变量,这样就会造成全局变量的污染,导致内存泄漏;


         

上面这些情况大家应该都很常见,这些都是可能会造成内存泄漏的原因之一,但是用了这么多年也没见过内存泄漏的问题,这是为什么呢?


为什么会内存泄漏


上面说了内存泄漏的原因,但是要搞明白为什么会内存泄漏,就得先了解一下什么是内存


内存就是我们在定义变量的时候,给变量分配的空间,这个空间是有限的,当我们定义的变量超过这个空间的时候,就会造成内存溢出


内存泄漏就是我们定义的变量没有被释放,导致内存空间被占用,当我们定义的变量超过这个空间的时候,就会造成内存溢出


所以内存泄漏的本质指的是内存溢出,只不过内存溢出也有很多原因,内存泄漏只是其中的一种;


见证一下内存泄漏


上面说了这么多,我们来看一下内存泄漏的例子,也就是最开始我们提到的闭包


         

上面这个例子是一个简单的缓存函数,我们可以通过这个函数来缓存一些数据,但是这个函数有一个问题,就是缓存的数据一直不会被释放,导致内存泄漏;


我们一秒钟就会缓存一个数据,这样就会导致内存一直增加,我们可以通过Performance来查看内存的使用情况,如下图:

image.png

可以看到内存曲线是一只在增加,没用下降的趋势,这种情况一般都是内存泄漏;


V8 的垃圾回收机制


上面我们已经知道了什么是内存泄漏,但是我的标题说内存泄漏并不是我们需要关心的,这里就要说到V8的垃圾回收机制了;


在网上查资料大多数人都能查到浏览器的垃圾回收机制分为两种,一种是标记清除,一种是引用计数


由于引用计数存在循环引用的bug,所以现在浏览器主流的垃圾回收机制基本上都是标记清除V8的垃圾回收机制是分代回收


分代回收指的是将内存分为新生代和老生代,新生代的内存空间比较小,老生代的内存空间比较大,新生代的内存空间会比较频繁的进行垃圾回收,当新生代的内存多次没有被回收的时候,就会被移动到老生代;

老生代的内存空间比较大,所以垃圾回收的频率比较低,但是垃圾回收的时候会暂停js的执行,所以垃圾回收的频率不能太高,否则会影响js的执行;


其实垃圾回收和内存泄漏的关系并不大,它关心的是有没有不需要用的内存需要回收,但是上面说到了垃圾回收的时候会暂停js的执行;


所以存在内存泄漏的时候,垃圾回收的执行时间会变长,这样就会影响js的执行,我们的页面就开始卡顿了;


不需要关心的内存泄漏


我们不需要关心的内存泄漏是因为浏览器运行在客户端,上面说到了在内存泄漏的时候,垃圾回收的执行时间会变长,这样就会影响js的执行,我们的页面就开始卡顿了;


作为一个普通用户,我发现页面突然变卡了,我这个时候直接刷新页面不就好了,这个时候内存会被重置,内存泄漏的问题就解决了;


所以老是纠结内存泄漏的问题,其实是不需要的,除了我上面说到的普通用户遇到卡顿的情况会直接刷新页面以外,浏览器在这一块也做了很多优化;


例如Chrome浏览器,当tab页没有被激活的时候,页面将会被冻结,这个时候页面的js执行就会被暂停,等重新激活的时候,页面的js执行就会继续;


这样就可以延长页面使用的时间,也就是延长了内存泄漏的时间,这样就可以避免内存泄漏的问题;


除了这个点以外,还有其他的优化,在通常情况除非你故意去制造内存泄漏,否则我们不需要关心内存泄漏的问题;


需要关心的内存泄漏



上面说到了不需要关心的内存泄漏,那么我们需要关心的内存泄漏是什么呢?


我们普通的业务仔几乎不需要关心,但是有些特殊的业务仔就需要关心了,例如页游直播canvaswebgl等等;


但是上面这些一样通过刷新页面就可以解决,需要关心,但是也可以接受,但是有一种情况就不一样了,那就是node


node运行在服务端,内存是非常宝贵的,如果内存泄漏,那么就会导致内存越来越少,最后就会导致node服务挂掉,这个可是大事;


node的内存泄漏和上面提到的内存泄漏是一样的,但是前端业务仔你需要写node的代码吗?所以前端业务仔不需要关心内存泄漏;


如何避免内存泄漏


上面说到了内存泄漏的问题,那么我们如何避免内存泄漏呢?


其实避免内存泄漏的方法很简单,就是设置一个阈值,当达到这个阈值的时候,就清空缓存;


拿我上面写的例子来说,我们可以设置一个阈值,当达到这个阈值的时候,就清除最早的缓存,这样就可以避免内存泄漏的问题;


         

上面清除最早的值是错误的写法,因为使用对象作为缓存,对象的键值顺序不是固定的,只是为了演示才这样写。


上面设置阈值之后,内存不会一直增加了,最后会恒定在一个值,如下:


image.png


可以看到内存不会一直增加了,最后趋近于一个值,这样就避免了内存泄漏的问题;

总结


内存泄漏在前端其实是一个很常见的问题,明明很常见,面试经常问,实际很少去解决这个问题,因为我们不需要关心;


我们知道内存泄漏的原因,知道怎么解决就行了,但是并不需要过多的关心,是在不行让用户自己去刷新就行了;


如果哪天真的遇到这个问题需要解决,那么工作汇报不就有东西写了,升职加薪指日可待,哈哈哈


目录
相关文章
|
1天前
|
缓存 Dubbo Java
案例 1: 某财险承保系统内存泄漏问题
案例 1: 某财险承保系统内存泄漏问题
|
7月前
|
监控 前端开发
揭秘跨部门沟通的秘密武器:让不归你管的人主动配合你的绝妙方法!
揭秘跨部门沟通的秘密武器:让不归你管的人主动配合你的绝妙方法!
68 0
|
存储 分布式计算 监控
为什么工作三年的程序员还不懂APM与调用链技术?
服务调用链技术 服务调用链技术是微服务架构中对服务进行监控的重要环节,它可以帮助我们清晰地了解当前系统的运行情况,同时帮助我们定位问题,解决分布式网络下服务交互追踪的问题
|
Unix Java Linux
系统的混乱并非业务本身之复杂,我们并不擅长处理『简单』
软件工程最大的成本在于维护,为了未来可扩展、为了未来更灵活,我们往往会增加很多很多奇奇怪怪可有可无的代码,增加这些代码可能只需要几分钟,但移除这些代码花费的精力与承担的风险,却数倍于此。我们不断 YY 着所谓的未来,却让现在越来越糟。系统的混乱并非业务本身之复杂,我们并不擅长处理『简单』。
1108 1
系统的混乱并非业务本身之复杂,我们并不擅长处理『简单』
|
Unix Java Linux
系统的混乱并业务本身之复杂,我们并不擅长处理『简单』
![](https://ata2-img.oss-cn-zhangjiakou.aliyuncs.com/neweditor/846d5052-1e21-4f9c-8f52-aaa37cacc407.png) # 前言 一群高智商青年在餐厅吃饭,餐桌上一个瓶盖标识为盐的瓶子里装得是胡椒粉,而标识为胡椒粉的瓶子里装得却是盐,他们想出了一个充满才气的方案来完成对调--仅需要一张餐巾纸、一根吸管和两个
48592 10
系统的混乱并业务本身之复杂,我们并不擅长处理『简单』
相亲软件开发,关注应用启动优化的本质
相亲软件开发,关注应用启动优化的本质
相亲软件开发,与用户留存息息相关的系统状态
相亲软件开发,与用户留存息息相关的系统状态
|
设计模式 安全 测试技术
如何快速理解复杂业务,系统思考问题?
对于复杂问题的思考其实是有层次的,从最表面的事件,到事件背后的规律,再到这个问题的结构模式,再到价值观,层层递进。在画完自己的业务系统因果回路图之后,再结合这个心智模型,思考自己的思考在哪个层次,是否可以有机会再下钻到更深的层次。
1186 2
如何快速理解复杂业务,系统思考问题?
|
Java
工程师什么时机最合适选择跳槽?
聊一下跳槽这个事。在 Java 工程师的职业生涯中,跳槽几乎是我们每一位工程师都会经历的事情。但在面试前需要考虑清楚:现在到底应不应该跳槽?
124 0