解决问题的办法:

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

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

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

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

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

  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. 对于组件,需要关注几个钩子,若组件中存在业务逻辑,则需要存在
  3. vue的写法:
    • created 该钩子中定义好,js层需要的变量
    • destroyed 该钩子中销毁,JS层使用的变量,手动释放。别犹豫

小程序写法:

  • onLoad 该钩子中定义好,js层需要的变量
  • onUnload 该钩子中销毁,JS层使用的变量,手动释放。别犹豫

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

  • 小程序的组件之间不能再过于耦合,要通过组件刷新更新子组件,也不要用 $ref 操作去调用子组件的变量或者方法。切记不能套娃写法
  • ws推送,3秒为一周期,应该将该周期的内的数据推送进行统一收集后再更新数据,这里的逻辑是,接口 –> 数据复制 —> setdata—> 更新视图。 这里减少任何一个环节的次数,都是优化的点。

Leave a Reply

Your email address will not be published. Required fields are marked *