正文从这开始~

内存问题对于后端童鞋而言可能是家常便饭,特别是C++童鞋。我在实习时做过半年的c++游戏客户端开发(也是前端开发哦),也见识了各式各样的内存问题,就说说我的第一个坑,当时做个需求,就是在玩家名字上加些酷炫的封号(就是下图中红框中的图片),人小不懂事,频繁去new一个图像出来,却不去释放它,导致客户端跑个几个小时就会崩溃,虽然很快就被揪出来修复掉,却也留下了心理阴影(5年了,依然历历在目啊)。

话题回到前端开发,很幸运,js还是拥有比较完善的gc机制,使得我们不需要时时刻刻像C++那样去关心内存问题。甚至说在传统网页开发中,极少需要去关注内存泄漏问题,因为即使有些许内存泄漏,页面刷新又将内存拉回起点。但随着SPA的流行,特别是移动app的火爆,js的内存问题也许会成为体验的瓶颈。

什么是内存泄漏

来自wikipedia的解释:“由于疏忽或错误造成程序未能释放已经不再使用的内存”。其实在有gc的高级语言中,我们可以定义得更仔细一点:“当我们不再使用某块内存的时候,却不让gc去回收它“。

js的内存管理机制以及一些常见的js内存泄漏点,本文就不一一介绍了,网上上已经有不少好的文章将这些点讲的很清楚。有兴趣的可以自行搜索。

什么样的内存泄漏是致命的

我写了一个内存泄漏的公式:

(n: 总共n个内存泄漏的地方;m:单个内存泄漏点所占用的内存;f:单个内存泄漏点的频次)

web前端的内存泄漏不像server端,server端哪怕一个极小的内存泄漏,都会因为海量的请求被放大(f极大),内存泄漏对于server端来说是致命的。但对于web前端来说,大部分的操作都很低频,也就是说很多时候,即使有内存泄漏,但是在整个页面生命周期里面,内存泄漏只是也只是增长了很少一部分,对用户体验很难造成影响。那么什么样的情况会导致致命issue?

我们来分析下上面公式中中的三个因子(很明显三个因子都对结果都是正相关关系):

1. m(单次内存泄漏的内存量)

无论是前端还是后端,想要单次泄漏较大量的内存还是不容易的,即使有这样的情况发生,想要找出根源也相对比较容易的,这种情况请开发不要作死。

2. f (单个内存泄漏频次)

我在km上搜到的前端js(不包含node)内存实战记录,zone miniportal 内存泄漏分析和经过和MiniPortal JS内存泄漏定位二(内部文章),虽然是09年的事情了,但我认为还是非常有代表性的。论大小pv上报返回的image对象,ajax获取的xml文件这能有多大?2k?但是在长时间打开的qzone页面上被一次又一次的执行,终成影响体验的大问题。

我也粗略总结下前端的一些高频操作(欢迎补充):

  • 强交互应用中的ajax或者socket请求处理

  • setInterval, requestAnimationFrame等循环处理

  • click等高频处理函数

我处理过的内存泄漏问题中,bc的情况其实是很少的,主要致命的内存泄漏出现在a情况,因为大部分请求都可能伴随着页面的局部刷新,特别是引入第三方框架时(比如chart相关,highchart、d3等),仅仅remove相应dom一般不会释放第三方对象,这时候就需要手动进行destroy。

例:用vue包装的highchart组件需要在组件生命周期末端进行销毁

反例:某知名报表系统, 页面如下:

点击刷新后监控内存变化,下图中四组内存快照分别是初始,请求20次,请求40次,请求60次时的内存情况(有兴趣的可以用timeline进行实验)。因为每次刷新的数据是一致的,将snap4雨snap3进行比较,按照大小进行分类会看到有不少每20个一组的内存块,再查看它的gc路径,泄漏点就显而易见了,真的是chart先动手的。

想象一下你的移动webapp在刷页面是刷占了300M的内存。。。。。。。。

3. n(总共n个内存泄漏的地方)

在传统网页中,单个页面中的内存泄漏点还是屈指可数的,但是在SPA中,页面的跳转并没有刷新,上个页面的内存泄漏点很有可能也不会被释放,这就会导致内存会一直递增,在某个阶段爆发,这正是SPA所面临的内存挑战。

举个非常普遍的例子Popup,因为点击其他区域时,需要隐藏弹出框,我们会在document上绑定click事件来处理隐藏的逻辑,如果在组件被销毁时,没有去解绑该事件的话,就导致了该处理函数中的引用无法被释放,在这个例子中这个popup对象都不会被释放。现在最流行的vue组件库element ui就存在这样的问题,谁有空可以去提个issue。

正面例子:在生命周期末期记得unbind

最后,今天的文章长度会适中吗?可能你还需要了解看看以下为你推荐的文章:

【第591期】4类 JavaScript 内存泄露及如何避免

【第528期】了解 JavaScript 应用程序中的内存泄漏

转---单页面应用下的JS内存管理的更多相关文章

  1. 闭包 与 js内存管理

    参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Memory_Management            https://blog ...

  2. vue单页面条件下添加类似浏览器的标签页切换功能

    在用vue开发的时候,单页面应用程序,而又有标签页这种需求,各种方式实现不了, 从这个 到这个,然后再返回上面那个 因为每个标签页的route不一样,导致组件重新渲染的问题,怎么都不知道如何实现... ...

  3. iOS 下ARC的内存管理机制

    本文来源于我个人的ARC学习笔记,旨在通过简明扼要的方式总结出iOS开发中ARC(Automatic Reference Counting,自动引用计数)内存管理技术的要点,所以不会涉及全部细节.这篇 ...

  4. angular ,require.js, angular-async-loader实现单页面路由,控制器js文件分离

    https://github.com/heboliufengjie/appRoute/tree/re re 分支,实现,路由配置,控制器js文件分离

  5. 单页面应用下刷新当前iframe

    $('button.layui-btn-elastic-2').click(function(){ var srcIframe=$(".layui-side ul li dd"). ...

  6. Windows平台下主要的内存管理途径

    new / delete   malloc / free    CoTaskMemAlloc / CoTaskMemFree    IMalloc::alloc / IMalloc/free    G ...

  7. JS内存管理

    背景: 分配给Web浏览器的内存通常比分配给电脑桌面的内存少,因为担心运行JS的网页耗尽全部系统内存而导致系统崩溃 内存限制问题不仅影响给变量分配内存,还会影响调用栈以及在一个线程中能够同时执行的语句 ...

  8. JS内存管理与垃圾回收

    内存分配 var n = 374; // 为数字分配内存 var s = 'sessionstack'; // 为字符串分配内存 var o = { a: 1, b: null }; // 为对象及其 ...

  9. JS内存管理测试

    打开调试器,切换到timer,点击左下角的record按钮开始,切换到memory视图,在文档中点击鼠标左右键,看股价走势图 function Allocate(kbs){ this.mem = ne ...

随机推荐

  1. 数位dp小结

    数位dp其实就是一种用来求区间[l, r]满足条件的数的个数.数位是指:个十百千万,而在这里的dp其实相当于暴力枚举每一位数. 我们通过把l, r的每位数分解出来,然后分别求r里满足条件的数有多少,l ...

  2. MVCS框架的注意点

    1.Service最好用一个接口对应一个service(便于增加扩展方法) 2.除Services和Model外都需继承自各自对应的父类 3.View不要轻易重写Start和Awake方法(含与启动有 ...

  3. SELECT INTO创建临时表

    SELECT INTO创建临时表 SQL Server临时表有两种类型:本地和全局.它们在名称.可见性以及可用性上有区别.本地临时表的名称以单个数字符号 (#) 打头:它们仅对当前的用户连接是可见的: ...

  4. UVaLive 3357 Pinary (Fib数列+递归)

    题意:求第 k 个不含前导 0 和连续 1 的二进制串. 析:1,10,100,101,1000,...很容易发现长度为 i 的二进制串的个数正好就是Fib数列的第 i 个数,因为第 i 个也有子问题 ...

  5. C#和java的对比及总结

    1.Java里的AClass.class得到的Class<T>类的对象对应C#的typeof(AClass)得到的Type类型的对象:(但是C#如果要反射创建对象是用Type对象的Asse ...

  6. 怎样导入现有的NiosII工程

    查找路径

  7. css基本图形绘制(基本的矩形、圆形、椭圆、三角形、多边形,也包括稍微复杂一点的爱心、钻石、阴阳八卦等)

    正方形: 代码: <style> .square { width: 100px; height: 100px; background-color: cornflowerblue; } &l ...

  8. Silverlight样式定义

    方法一.定义在控件内部 <Canvas Background="Red" Height="100" HorizontalAlignment="L ...

  9. 动态创建控件 #Create(...)

    在类中创建一个控件对象;例:CButton m_btn; 用Create创建一个对象(#其实已经与其绑定)m_btn.Create(.....); #注意Create()函数的参数 问题一:点击一个b ...

  10. java的并发和多线程

    本文主要讲解Java并发相关的内容,包括锁.信号量.堵塞队列.线程池等主要内容. 并发的优点和缺点 在讲述怎么利用多线程的情况下,我们先看一下采用多线程并发的优缺点. 优点 提高资源利用率 如读取一个 ...