Flutter 性能优化之降内存、降刷新篇

1. 情景还原

Flutter 性能优化之降内存、降刷新篇_第1张图片

设想一下

APP 从点击启动到可以浏览页面需要 10 秒多;

玩一会儿页面卡住了;

玩一会儿流量耗没了;

玩一会儿手机发烫了;

玩一会儿手机没电了;

玩一会儿应用闪退了;

作为用户,你会怎么做?重启、开骂、投诉、卸载...

作为开发,你会怎么做?领问题,解决。

‘我’收到的反馈

一、根据线上崩溃系统反馈,有一类崩溃出现过 2 个高点:2.19 号,3.12 号:

Flutter 性能优化之降内存、降刷新篇_第2张图片

根据崩溃栈,结合主线同学的排查结论,与之前商城团队线上出现过的崩溃问题现象一致:初步定位到图片组件问题:换图片组件 extended_image。

二、测试同学反馈,APP 页面偶现卡顿,上下滑动不流畅,影响体验。

行文至此,基于上述两点反馈,急需协调资源来着重处理下性能问题。

2. 优化方向

基于以上两点,经团队内部推演、讨论:决定从 2 个维度尝试一下性能优化:降内存、降刷新。

2.1 优化方向定位

1.调研梳理所有优化方向,确定图片压缩、更换图片组件、降低页面刷新次数三个方向

Flutter 性能优化之降内存、降刷新篇_第3张图片

2.性能优化流程

2.2 降内存- 图片优化

使用 iOS-Xcode、Android-Android Studio 开发工具来查看 APP 内存占用; 按照 Flutter 官方的性能优化指南,Flutter-profile 模式下,使用 devTools 查看 Flutter 内存占用;

查看电量(为后续 profile 模式分析 APP 耗电,提供查看窗口):

Flutter 性能优化之降内存、降刷新篇_第4张图片

Flutter 性能优化之降内存、降刷新篇_第5张图片

Flutter 性能优化之降内存、降刷新篇_第6张图片

由于智家 APP 壳工程 profile 模式正在攻克中,故暂时在 debug 模式下寻找内存泄漏点。

2.2.1 识别 

2.2.1.1 高内存

全屋智能为例:为固定测试变量,排除干扰项,屏蔽应用日志输出。

通过 Xcode 性能调试窗口可知,iOS 端智家 APP 的运行内存 1.32G 左右;

通过 Android Studio 的 profile 窗口可知,Android 端智家 APP 的运行内存在 1.4G 左右;

直觉:存在高内存问题。

Flutter 性能优化之降内存、降刷新篇_第7张图片

Flutter 性能优化之降内存、降刷新篇_第8张图片

2.2.1.2 过载图片

全屋智能页由 Flutter 开发,故切换到 Flutter 调试模式,继续分析(暂用 debug 模式,profile 模式暂不支持);

图片过载检测:切换到 Flutter Inspector,点击 Highlight Oversized Images

通过过载检测日志可知,有很多图片存在过载,需内存优化;

每张图片产生 20M 的额外内存;假设列表长度为 100,若内存回收不及时,理论上短时间内会产生 20M * 100 = 2G 左右内存浪费,存在卡顿、闪退风险。

Flutter 性能优化之降内存、降刷新篇_第9张图片

Flutter 性能优化之降内存、降刷新篇_第10张图片

随机下载一张设备图片查看:

http://file.c.haier.net/images/2020/09/21/9268581c6c842ad16bdd72ef06d95e28.png

图片很大 -2000x2000 1.78M

一个设备卡片的设备图标,显示区域只需要 48x48,网络图是 2000x2000,优化空间很大。

2.2.2 方案 

2.2.2.1 网络图片压缩

与海极网同学确认,设备图片存放在阿里云 oss 服务器,故可以使用 oss 图片压缩参数:

原始图片:http://file.c.haier.net/images/2020/09/21/9268581c6c842ad16bdd72ef06d95e28.png

前端适配:http://file.c.haier.net/images/2020/09/21/9268581c6c842ad16bdd72ef06d95e28.png ?x-oss-process=image/resize,m_fixed,h_100,w_100

(注:压缩尺寸设置过小会造成图片失真,具体压缩尺寸需根据显示区域自行调整)

(阿里云 OSS 图片处理-官方指南:OSS 图片处理中的图片缩放功能参数及示例_对象存储-阿里云帮助中心)

图片压缩后,再次检测 APP 的运行时内存占用:

Flutter 性能优化之降内存、降刷新篇_第11张图片

Flutter 性能优化之降内存、降刷新篇_第12张图片

此时检测图片过载情况:

Flutter 性能优化之降内存、降刷新篇_第13张图片

Flutter 性能优化之降内存、降刷新篇_第14张图片

图片 oss 压缩后,过载问题解决,APP 运行内存下降(debug 模式比 profile 模式略高):

  • iOS:1.32G -> 693M 内存降低 627M;

  • Android:1.4G -> 900M 内存降低 500M;

延伸:通过控制台可以发现,有很多图片存在不同程度的过载问题,此时可以逐一压缩验证,限于篇幅不展开赘述。

智家页按上述图片过载检测流程走一遍,也存在图片过载情况:

Flutter 性能优化之降内存、降刷新篇_第15张图片

抓取轮播图 下载查看-大小超限:

"pictureUrl" -> " https://oss-zjrs.haier.net/content/img/2023030317202286396302.jpg "

"pictureUrl" -> " https://oss-zjrs.haier.net/content/img/2023030309343396429763.jpg "

Flutter 性能优化之降内存、降刷新篇_第16张图片

与 UE 同学确认:该 Banner 的图片要求:宽/高=4; 这两张图都符合要求:一个是 3 倍图,一个是 2 倍图。(若尺寸不对或图片过大,可联系运营同学替换为合规图片)

图片合规,故前端压缩处理即可,有两种处理方式:

  1. 现有图片组件增加 ResizeImage 或 cacheWidth/cacheHeight;

  2. 替换有 cacheHeight 处理的新组件 extended_image;

从前后对比效果来看,选择第 2 种方案。

重新对图片过载检测,无过载提示,故 Banner 图片过载问题解决。

2.2.2.2 本地图片压缩

网络图片可以采用 oss 压缩;本地图片如何处理?

根据官方文档说明,以及图片过载检测控制台优化提示,给本地图片增加 cacheHight 或 cacheWidth;或使用 ResizeImage 组件包裹。

Flutter 性能优化之降内存、降刷新篇_第17张图片

注:cacheWidth/cacheHight = width/height * 像素密度,如:

Flutter 性能优化之降内存、降刷新篇_第18张图片

具体显示效果还是需自行参数调整、验证。

其他页面类似,按照此路径检测下是否存在图片过载情况。

2.2.2.3 换图片组件-ExtendedImage

经网络图片综合对比,目前 extended_image 组件表现最优。

extended_image 组件内置 ResizeImage-cache 处理,故会处理一部分图片压缩功能。

网络图片组件

已知问题

使用情况

CachedNetworkImage

线上偶现崩溃(未 100%确认)

线上 Flutter 页面还有使用,正在逐步切换;

NetworkImage

Image.network()

iOS 端:偶现断网再恢复网络图片不重新加载问题;(HDS-bug)

替换组件:extended_image,解决

extended_image

1 已知:商城、场景、首页;

2 其他 Flutter 业务(智家、3+5、Flutter 主框架等)也在逐步替换为该网络组件;

2.2.3 效果

至此,降内存有所成效:

通过对网络图片 oss 压缩,对本地图片设置 cacheHight/cacheWigth,内存降低。

另:为防止出现线上的 11730 崩溃(图片组件),将网络图片组件逐步替换成 extended_image。

2.3 降刷新 - 刷新次数优化

降低页面刷新,从两个点去分析:动效/局部 UI 刷新 导致重绘;大量逻辑计算驱动页面刷新。

2.3.1 识别- 定位重绘区域 

Flutter Inspector - Highlight Repaints

Flutter 性能优化之降内存、降刷新篇_第19张图片

UI 组件周边会出现彩色边框,UI 重绘时彩色边框会动态变色,类似跑马灯(如上图 gif),有 UI 重绘。

根据官方性能优化指南,若出现组件 A 重绘(动效、轮播等):

  • 使用重绘组件包裹 A:RepaintBoundary Widget ;该组件会创建额外绘制画布

  • 缺点是:增加一定内存消耗

从现象来看,直接页轮播图并未造成其他区域重绘,故无需特殊处理;若引起其他区域重绘,需逐步排查解决。

各页面可根据重绘情况,酌情考虑优化方案(控制 setState 粒度、引入全局状态管理-redux/Provider、拆分 ViewModel、减少 build() 操作 等)。

2.3.2 方案-订阅关系优化 

经过逻辑梳理,发现一个点:智家页的属性订阅、解订阅逻辑存在优化空间。

页面销毁、无设备时才进行设备解订阅,比较难触发; 页面不在前台时订阅关系仍在,会造成不必要的属性去重计算和日志输出,造成 CPU、内存浪费。

打开 APP 日志开关,抓取日志验证:卡片列表稳定后-页面处在非前台,抓取 1 分钟日志,过滤属性变化相关日志:

优化前:vm_update 510 条左右 * N 分钟

Flutter 性能优化之降内存、降刷新篇_第20张图片

理论上:日志量和属性去重计算次数 与时间呈线性关系y = ax + b

Flutter 性能优化之降内存、降刷新篇_第21张图片

订阅关系优化:

订阅关系优化

订阅时机

解订阅时机

优化前

1 设备列表初始化-订阅属性变化; 2 设备列表变化-订阅属性变化;

1 设备列表为空-解订阅属性变化; 2 页面销毁 dispose()-解订阅属性变化;

优化后

1 设备列表初始化-订阅属性变化; 2 设备列表变化-订阅属性变化; 3 页面进入前台-订阅属性变化;

1 设备列表为空-解订阅属性变化; 2 页面销毁 dispose()-解订阅属性变化; 3 页面进入非前台-解订阅属性变化;

订阅关系优化后,打开 APP 日志开关,抓取日志验证: 卡片列表稳定后-页面处在非前台,抓取 1 分钟日志,过滤属性变化相关日志:

优化后:vm_update 恒定 20 条左右(理论值为 0,由于日志抓取的时间前后误差-导致出现脏数据)。

Flutter 性能优化之降内存、降刷新篇_第22张图片

时间越长,日志量和属性去重计算次数 下降越明显,CPU 使用率降低越明显。

(由于 APP 开启全量日志后,对比条件加入了日志 IO 干扰,无法准确描述订阅优化前后 CPU 使用率对比)。

2.3.3 效果 

页面非前台解订阅,页面回前台重新订阅,100 个设备 1 分钟内:

  1. 去掉属性上报相关日志 - 510 条

  2. 减少属性去重计算次数 - 510 次

  3. 时间越长,优化效果越明显

3. 总结

Flutter 性能优化的手段有很多,其中很重要两点:内存占用和页面刷新。

Flutter 的性能分析模式 profile 还在攻关中;本期使用 debug 模式;

所有性能参数 均比线上真实业务场景高 不能体现真实页面性能;只能取差值对比。

profile 模式下的 CPU、内存、电量、等优化手段,APP 壳工程暂不支持 profile 模式,未展开说明,可自行查阅官方优化指南:Flutter performance profiling。

3.1 优化方案

本次通过以下几点尝试优化:

  1. 替换网络组件 extended_image;

  2. 图片 oss 压缩;

  3. 订阅关系优化:页面非前台及时解订阅,回前台重新订阅;

  4. 定位重绘区域:按需使用 RepaintBoundary 组件。

3.2 优化效果

降内存-内存使用明显下降:100 个设备,Android 平均下降 500M,iOS 平均下降 600M;

降刷新-属性去重计算下降:订阅关系优化后,抓取 1 分钟日志输出,减少 510 条;去重计算减少 510 条;

崩溃率-Flutter 图片崩溃率:待上线后通过监控系统,进一步跟踪线上崩溃趋势。

3.3 优化指南

官方性能优化指南路径清晰,方法全面,建议各位同学都尝试一下,发现更多优化点,让 APP 更流畅、更健壮。

性能最佳实践:Performance best practices | Flutter

官方性能分析:Flutter performance profiling | Flutter

4. 参考

  • 性能最佳实践:Performance best practices | Flutter

  • 官方性能分析:Flutter performance profiling | Flutter

  • 业内做法-携程:携程酒店 Flutter 性能优化实践 -51CTO.COM 、干货 | Flutter在携程复杂业务的高性能之旅

  • 业内做法 -58 :超级全面的 Flutter 性能优化实践 - 掘金

  • 业内做法-闲鱼:他把闲鱼 APP 长列表流畅度翻了倍(良心教程) - 掘金

  • 业内做法-京东:京东在 Flutter 加载大量图片导致的内存溢出的优化实践 | HeapDump 性能社区

  • 腾讯

    • MOO音乐的Flutter实战总结之内存治理(上)

    • MOO音乐的Flutter实战总结之内存治理(中)

    • 腾讯MOO音乐关于Flutter的内存优化策略(下) | HeapDump性能社区

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

  • HeapDump 性能社区专题系列七:大厂前端敲门砖——Flutter 的应用实践

  • Flutter混合栈路由实践与优化

  • https://github.com/awesome-tips/Flutter-Tips/blob/master/articles/Flutter%20%20%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E2%80%94%E2%80%94%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E5%BA%94%E7%94%A8%20jank.md

  • Flutter 性能优化 Tips,Android攒了一个月的面试题及解答_android_InfoQ写作社区

  • 深入探索 Flutter 性能优化 - 知乎

  • https://www.teqng.com/2021/09/14/%E5%B0%86%E5%9B%BE%E7%89%87%E5%BA%93%E4%BC%98%E5%8C%96%E5%88%B0%E5%BA%95%EF%BC%8C%E6%80%A7%E8%83%BD%E6%8F%90%E9%AB%9850%EF%BC%81%E4%BA%AC%E4%B8%9C%E4%BA%AC%E5%96%9Capp%E6%98%AF%E5%A6%82%E4%BD%95/

5. 团队介绍

三翼鸟数字化技术平台-网器管理平台」负责网器设备基础数据和计算、规则引擎、网器绑定、网器控制、安防音视频、网器跨平台接入验证等业务,服务产业及海尔智家线上用户;负责网器管理平台建设,提供产业设备基础数据底座、研发产业跨平台网器管理工具等,致力于提升用户交互体验和网器产品的智能化水平。

你可能感兴趣的:(研发,效能提升,flutter,性能优化)