这可能是,Flutter 中最“强悍”的内存泄漏检测方案......

这可能是,Flutter 中最“强悍”的内存泄漏检测方案......_第1张图片

近两年来,无论是创新型应用还是老牌旗舰型应用,都在或多或少地使用 Flutter 技术。然而,目前 Flutter 业务团队反馈最普遍的问题是,Flutter 内存占用过高

Flutter 内存占用过高原因比较复杂,需另开一个主题才能说清楚。简单总结下我们调研的结论:Dart Heap 内存管理以及 Flutter Widget 设计综合导致业务内存较高,其最核心的问题引擎设计使开发者容易踩中内存泄漏。开发过程中,内存泄漏常见且难以定位,总结主要 2 点原因:

  • Flutter 渲染三棵树的设计,以及 Dart 各种异步编程的特点,导致对象引用关系比较绕,分析困难

  • Dart “闭包”,“实例方法”可赋值传递,导致所在的类被方法上下文持有,不经意就会发生泄漏。典型例如注册一个 listener 没有反注册,导致 listener 所在的类对象泄漏

开发者享受了 Flutter 开发的便利性,却不知不觉中承受了内存泄漏的苦果。因此,我们迫切需要一套高效的内存泄漏检测工具来摆脱这种困境。

盘点我了解到的几种内存泄漏检测方案:

  1. 监控 State 是否泄漏:针对 State 的泄漏检测。但 State 是 Flutter 内存泄漏中占比最大的对象吗?StatelessWidget 的对象也是可以引用很大内存的

  2. 监控 Layer 个数:对比 正在使用,内存中的 Layer 个数来判定是否存在内存泄漏。方案对内存泄漏判定是否准确?Layer 对象离业务 Widget 太远,溯源太困难

  3. Expando 弱引用泄漏判定:判定特定对象是否泄漏并返回引用链 。但我们不知道 Flutter 中最应该监控的对象是哪个,哪个对象泄漏是主要问题?

  4. 基于 Heap Snapshot 内存泄漏检测:对比不同两个时间点的 Dart 虚拟机 Heap 对象的增长,以“class 内存增量”,“对象内存个数” 2 个指标检测发生泄漏的可疑对象。这是个通用的解决方案,但要做到高效定位到泄漏对象(Image, Layer)才比较有价值。目前“确定检测对象”和“检测时机”这 2 个问题都不好解决,所以还需要人工逐一排查确认,效率不高。

总之,我们觉得方案 1,2 逻辑上不够完备,方案 3,4 效率有待提高。

更好的方案是?

参考 Android,LeakCanary 能够准确、高效检测 Activity 内存泄漏,解决内存泄漏的主要问题。那我们能不能在 Flutter 中也实现一套这样的工具呢?这应该是一套更好的方案。

在回答这个问题之前,先思考下为什么 LeakCanary 要挑选 Activity 作为内存泄漏监控的对象,并且能够解决主要的内存泄漏问题?

我们总结其至少满足了下面 3 个条件:

  1. 泄漏对象引用的内存足够大:Activity 对象引用的内存是非常大,是内存泄漏的主要问题

  2. 能够完备定义内存泄漏:Activity 具有明确的生命周期和确切回收时机,泄漏定义完备,可实现自动化,提高效率

  3. 泄漏的风险高:Activity 基类为 Context,作为参数传递,使用非常频繁,存在较高的泄漏风险

3 个条件反映了监控对象的必要性,监控工具的可操作性。

顺着这个思路,如果我们能够在 Flutter 中找到满足上面 3 个条件的对象,将其监控起来,那就可以做一套 Flutter 的 LeakCanary 工具,用来解决 Flutter 中内存泄漏的主要问题。

从实际项目中回顾近期解决的内存泄漏问题,内存飙升体现在 Image, Picture 对象,如下图所示。

这可能是,Flutter 中最“强悍”的内存泄漏检测方案......_第2张图片

虽然 Image, Picture 内存占用高,是泄漏内存的主要贡献者,但它们不能作为我们监控的目标,因为它们明显不符合上面列出的 3 个条件:

  1. 内存占用大,是其对象个数多,累加起来的,并不是由某一个 Image 引用而导致

  2. 无法定义什么时候是泄漏的,没有明确的生命周期

  3. 并不会作为一个常用的参数传递,使用地方都比较固定,例如 RawImage Widget

深入 Flutter 渲染分析,总结到 Image, Picture 泄漏的根本原因是 BuildContext 发生泄漏。而 BuildContext 恰恰满足上面列的 3 个条件(后面详述),似乎是我们要找的那个对象,实现一套监控 BuildContex 泄漏的方案似乎不错。

请记住这 3 个条件,后面我们在说明的时候会经常用到。

为什么监控 BuildContext

BuildContext 引用的内存有哪

你可能感兴趣的:(java,开发语言,面试,职场和发展,后端)