性能文章>腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)>

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)转载

3周前
160201

导言

MOO 音乐是 TME 旗下的新锐音乐服务,其团队是公司内最早实践 Flutter 的先行者之一。本系列文章将提炼 MOO APP 开发中遇到的情况,就 Flutter 内存占用治理方面,分享日常开发的一些基本认知、注意要点、排查方法和优化方案。内存治理篇文章共分上、中、下三篇,本篇为中篇。

上篇已经介绍了关于Flutter的内存问题腾讯MOO音乐关于Flutter的内存治理(上),今天我们进入实战,来了解一下内存泄漏应该怎样解决!

 四、内存泄漏的排查实战

为了便于我们定位具体问题代码,Android Studio 或 VS Code 插件帮我们包装了相关内存工具,这些工具都基于 debug 模式下 Dart VM service 暴露的接口开发的,Dart VM service 自身也带有协助排查内存问题的工具 - Dart VM Observatory,attach 之后访问 service 提供的 http 链接即可使用该工具,内存排查功能路径为:Isolate (main)  --> Allocation Profile。

工具有了,如何排查定位导致内存泄漏的问题代码呢?

  • 对同一个功能或页面进行反复相同的进入、退出操作;
  • 然后执行强制 GC,查看不同操作后的内存快照;
  • 对比该功能关联的对象实例增加情况;
  • 如果强制 GC 后实例只增不减或该回收的对象没有被回收,没有特殊的延时处理一般就可以判断相关代码有问题。

下面以 Image 内存泄漏排查为例,展示具体的问题代码定位过程,目标是排查列表项内存泄漏,功能进出动作对应着列表项的滑窗动态创建和销毁。

1. 我们打开 APP 其中一个页面,如某个列表页,通过 Xcode 观察应用整体初始内存 470MB,如图所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

 

往下翻了几页,内存持续上涨,并且表现为一直翻页一直涨,这种情况大概可以确定页面存在内存泄漏问题,如图所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区



2. 打开自带工具 Allocation Profile 界面后,点击右上角 GC 按钮,强制回收所有可回收对象,如图所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

回收了可回收对象后,剩余的便是当前 Isolate 状态下的内存快照,都是强引用内存对象。

3. 根据初始内存快照和当前快照的对比,可明显看到图片实例有明显的增长,并且随着不断翻页持续增长,更明显超过了图片缓存的大小的限制。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

从这里我们可以确定 Image 对象实例存在引用没被释放的问题,下一步是找出 Image 引用的持有对象。

4. 点击 Image 链接,如图所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

进入新页面后找到 strongly reachable,展开可看到内存快照中具体的 Image 对象列表,如图七所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

5. 进入 Image 实例详情界面,如图八所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

6. 查找对象引用未释放的节点,通常要翻查外部对象引用链,从上图可以看出该 Image 实例最终被 _CacheImage 引用,是图片缓存正常持有的引用。

根据图片缓存的 LRU 机制,可以断定会存在图片缓存释放掉但被其他对象持有的 Image 实例对象,我们可以继续尝试别的 Image 实例排查其引用情况。

7. 经过随机翻查了一些 Image 实例,发现了一些线索,如图九所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

这个 Image 实例引用已经被 ImageCache 对象释放,但没有被正常回收。

8. 从引用链可以看出,DisplayDecorationImagePainter 对象是我们封装的类,ImageStreamListener 对象持有了相关引用,正是因为这个引用链导致了 Image 对象实例没被回收。

9.  翻查了一下代码,发现是由于 DisplayDecorationImagePainter 注销时没有给 ImageStream 反注册监听。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

10. 补充了反注册代码之后,重复前面的操作,持续滚动翻页,图片实例数量维持在 122MB 左右,内存也没有持续增长,如图十所示。

腾讯MOO音乐关于Flutter的内存泄漏的排查实战(中)数据图表-heapdump性能社区

到此,图片内存问题已经得到解决。

排查过程就是在对象实例的引用链上寻找代码线索的过程,针对图片泄漏的排查,可以设置一个较小的图片缓存阈值,减少图片对象缓存,干扰对象少了排查效率就大大更高。

排查泄漏是个频率较高的重复操作,通常排查特定功能都会关注特定的相关对象,自带的排查工具对关注的对象没有较好的过滤功能,而且操作路径长,引用链显示也不够直观。可以考虑自研排查工具来解决这个效率问题。

 

更多思考:

本次向大家介绍的是Flutter内存泄漏的优化方案,其实Flutter的各种优化都很多,大家可以通过阅读以下文章系统的学习Flutter!

Flutter混合栈路由实践与优化

美团FlutterWeb性能优化探索与实践

 

请先登录,再评论

暂无回复,快来写下第一个回复吧~

为你推荐

关于内存溢出,咱再聊点有意思的?
概述 上篇文章讲了JVM在GC上的一个设计缺陷,揪出一个导致GC慢慢变长的JVM设计缺陷,可能有不少人还是没怎么看明白的,今天准备讲的大家应该都很容易看明白 本文其实很犹豫写不写,因为感觉没有
谨防JDK8重复类定义造成的内存泄漏
概述 如今JDK8成了主流,大家都紧锣密鼓地进行着升级,享受着JDK8带来的各种便利,然而有时候升级并没有那么顺利?比如说今天要说的这个问题。我们都知道JDK8在内存模型上最大的改变是,放弃了Perm
JVM菜鸟进阶高手之路九(解惑)
关于MAT工具相关知识解惑MAT 不是一个万能工具,它并不能处理所有类型的堆存储文件。但是比较主流的厂家和格式,例如 Sun, HP, SAP 所采用的 HPROF 二进制堆存储文件,以及 IBM 的
JVM垃圾回收与一次线上内存泄露问题分析和解决过程
本文转载自:花椒技术微信公众号 前言内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。Ja
强如 Disruptor 也发生内存溢出?
前言```OutOfMemoryError ```问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界、空指针等)来说这类问题是很难定位和解决的。本文以最近碰到的一次线上内存溢出的定位、解决问题的
spring boot 引起的 “堆外内存泄漏”
背景组内一个项目最近一直报swap区域使用过高异常,笔者被叫去帮忙查看原因。发现配置的4G堆内内存,但是实际使用的物理内存高达7G,确实有点不正常,JVM参数配置是:```java-XX:Metasp
实战:一次疑似内存泄漏的问题排查
问题背景最近服务器到期等因素,进行了迁移。租了其它的外国厂商,但是由于资费问题,购买了1.5G 内存的服务器(现)。因为原本用惯了4G内存的服务器(原),现在压缩成这样,似乎不太能支持我的使用,囧!现
记录一次Flink作业异常的排查过程
最近2周开始接手apache flink全链路监控数据的作业,包括指标统计,业务规则匹配等逻辑,计算结果实时写入elasticsearch. 昨天遇到生产环境有作业无法正常重启的问题,我负责对这个问题