uniapp 内存溢出定位和优化方案

2022年5月26日 1037点热度 1人点赞 0条评论

解决问题的办法:

通过小程序自带的内存管理工具,查看小程序运行期间的内存变化

图片        

该功能能实时查看,小程序运行期间,内存占用情况。     

图片         

运行过程中,方形的柱子表示运行过程中,内存占用情况,若柱子中含有蓝色的,表示该运行产生了数据变量没有被系统回收,可能存在内存泄漏的风险


      图片
       

通过点击下面的堆栈信息,查看堆栈里面是否存在变量被挂到了全局中。

目前通过此方法发现项目存在问题:

  1. websocket建立之后,通过调用 getSocketMsg() 对 onMessage() 进行了重复监听,ws推送过来后,多次监听多次刷新。导致内存溢出

  2. 修改这个问题之后,发现,ws推送过来的数据都存在内存中,并没有使用完释放掉,这里与预期不符合,排查代码发现,对于函数的传参使用了匿名对象,理论上使用完就会释放掉,但由于代码的嵌套写法,导致了函数闭包,无法触发回收机制。改成变量赋值,用完手动释放

  3. uniapp中使用console.log异常报错,都会在内存堆栈中常驻,不会释放,若你打印了某对象,该对象会一直常驻内存,目标是方便调试,查看堆栈信息,若使用不当,会引发内存泄漏。

  4. 对于WS推送过来的数据,接收后马上更新数据,该方式存在一定的隐患。自选列表中每条股票的数据信息都会单独推送一条,若10条自选 - 推送10 - 前端接受10次 - dom刷新10次。该逻辑整理为:10条自选 - 推送10次 - 前端合并成1次 - 1次dom更新。性能得到显著提升。

  5. 页面中组件,在页面切换之后并没有销毁,也常驻内存中,而且页面重新打开之后不仅没有复用,反而新开了一个组件。这里有点匪夷所思。排除之后发现,是组件嵌套太深,并且有父组件通过 $ref 调用子组件的变量,由于父组件没有销毁,子组件也不会销毁。例如:canvas 和 分时图之间的关系就存在这个内存泄漏的问题。

上述为通过 内存工具定位和代码review,定位到已知性能问题。并且都已经修复

目前需要调整的开发规范:

  1. js的对象直接赋值 是 属于浅复制,你理解为引用即可。这里需要关注点就是 JS 的垃圾回收机制是引用计数回收即变量被0次引用则回收。A变量引用了B变量,A不回收,B则不回收。该手动释放的就要手动释放。

  2. 对于组件,需要关注几个钩子,若组件中存在业务逻辑,则需要存在

    • vue的写法:

      • created  该钩子中定义好,js层需要的变量

      • destroyed  该钩子中销毁,JS层使用的变量,手动释放。别犹豫

    • 小程序写法:

      1. onLoad  该钩子中定义好,js层需要的变量

      2. onUnload 该钩子中销毁,JS层使用的变量,手动释放。别犹豫

要特别注意一下 onHide 和 onUnload的区别,跟打开方式有关系 点击这里查看说明

  1. 小程序的组件之间不能再过于耦合,要通过组件刷新更新子组件,也不要用 $ref 操作去调用子组件的变量或者方法。切记不能套娃写法

  2. ws推送,3秒为一周期,应该将该周期的内的数据推送进行统一收集后再更新数据,这里的逻辑是,接口 --> 数据复制 ---> setdata---> 更新视图。这里减少任何一个环节的次数,都是优化的点。

35900uniapp 内存溢出定位和优化方案

这个人很懒,什么都没留下

文章评论