正文从这开始~

内存问题对于后端童鞋而言可能是家常便饭,特别是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. 对 Service中sqlsession对象的优化

    在本线程中添加object数据,必须在本线程中才能获取出来..其他线程获取不到. public class Test { public static void main(String[] args) ...

  2. 谷歌开源OCR,tesseract-ocr使用笔记

    官方教程地址:https://github.com/tesseract-ocr/tesseract/wiki/Compiling 测试版本为 root@9a2a063f9534:/tesseract/ ...

  3. JMeter压力测试及服务器状态监控教程

    转载自:https://blog.csdn.net/cbzcbzcbzcbz/article/details/78023327 前段时间公司需要对服务器进行压力测试,包括登录前的页面和登录后的页面,主 ...

  4. CURL模拟表单post提交及相关常用参数的使用(包括提交表单同时上传文件)

    转载自:https://blog.csdn.net/freedomwjx/article/details/43278157 (注:在curl前面加上time如time curl xxx,可以在最后显示 ...

  5. keras CNN解读

    loss是训练集损失值.  acc是训练集准确率.val_loss是测试集上的损失值,val_acc是测试集上的准确率. 用深度学习框架跑过实际问题的朋友一定有这样的感觉: 太神奇了, 它竟然能自己学 ...

  6. linux初学terminal命令(1)ls、cd、su、man、pwd、useradd、passwd、cat、Ctrl+C、Ctrl+Z、Ctrl+L

    terminal命令(terminal终端对应windows 按下win(linux下叫Super键)+r,输入cmd(command,命令),召唤出来的Dos控制台) 1. ls(英文list):简 ...

  7. eclipse查看方法被那些代码调用open call hierarchy

    当我们编写的代码量十分巨大,项目十分复杂的时候,想要查找某一个方法都被其他那些代码调用了是一件十分困难的事,然后Eclipse提供了十分方便的方法用于查看方法都被那些代码调用了. 方法一: 选中要查看 ...

  8. noip第17课作业

    1.  召见骑士 [问题描述] 某王国有5位骑士,每位骑士都有自己的编号,且这个王国的编号都为奇数,分别为1,3,5,7,9,在国王召见他们之前他们都必须经过只能从一边进出的长廊,长廊的宽度只能坐一个 ...

  9. SRM474

    250pt 题意:在一个N维的空间里,有一个人开始在原点,现在给出N<=50个指令序列,每个指令序列为某一维+1或者减一,问是否经过某个点至少2次. 思路:操作很小,直接模拟判断即可 code: ...

  10. 调用azkaban接口,upload 本地zip文件

    使用azkaban部署任务,可以将job文件打成zip包,通过web页面上传. 如图 但是当我们实践CI持续化部署的时候,要实现自动的部署上线. 这时就要调用azkaban提供的api. 地址如下:h ...