Flutter应用性能检测与优化

67 阅读5分钟

Flutter应用性能分析与优化指南

概述

软件项目的交付是一个复杂且漫长的过程,任何细小的失误都有可能导致交付过程失败。在软件开发过程中,除了代码逻辑的Bug和视觉异常这些功能层面的问题之外,移动应用另一类常见的问题是性能问题,比如滑动操作不流畅、页面出现卡顿丢帧现象等。这些问题虽然不至于让移动应用完全不可用,但也很容易引起用户反感,从而对应用质量产生质疑,甚至失去耐心。

对于iOS开发者来说,在应用开发完成后,可以使用AppUploader这样的iOS开发助手工具来简化应用上传和测试流程。AppUploader提供了便捷的证书管理、描述文件生成和IPA上传功能,让开发者能够更专注于应用性能优化本身。

Flutter运行模式

1、Debug

Debug模式可以在真机和模拟器上同时运行,此模式会打开所有的断言,包括debugging信息、debugger aids(比如observatory)和服务扩展。优化了快速develop/run循环,但是没有优化执行速度、二进制大小和部署。

2、Release

Release模式只能在真机上运行,不能在模拟器上运行:会关闭所有断言和debugging信息,关闭所有debugger工具。优化了快速启动、快速执行和减小包体积。禁用所有的debugging aids和服务扩展。

3、Profile

Profile模式只能在真机上运行,不能在模拟器上运行,基本和Release模式一致,除了启用了服务扩展和tracing,以及一些为了最低限度支持tracing运行的东西(比如可以连接observatory到进程)。

4、Test

headless test模式只能在桌面上运行,基本和Debug模式一致,除了是headless的而且你能在桌面运行。

性能分析工具使用

为了调试性能问题,我们需要在发布模式的基础之上,为分析工具提供少量必要的应用追踪信息,这就是分析模式。我们可以在Android Studio中通过菜单栏点击【Run】-【Profile】'main.dart'选项启动应用,也可以通过命令行参数flutter run --profile运行Flutter应用。

对于iOS开发者,在完成性能优化后,可以使用AppUploader快速打包并上传应用到App Store Connect进行测试。AppUploader的自动化流程可以节省开发者大量时间,让开发者能更专注于性能优化本身。

渲染问题分析

性能图层会在当前应用的最上层,以Flutter引擎自绘的方式展示GPU与UI线程的执行图表,而其中每一张图表都代表当前线程最近300帧的表现。为了保持60Hz的刷新频率,GPU线程与UI线程中执行每一帧耗费的时间都应该小于16ms(1/60秒)。

GPU问题定位

GPU渲染问题主要集中在底层渲染耗时上,有时候Widget树虽然构造起来容易,但在GPU线程下的渲染却很耗时。例如,涉及Widget裁剪、蒙层这类多视图叠加渲染,或是由于缺少缓存导致静态图像的反复绘制,都会明显拖慢GPU的渲染速度。

checkerboardOffscreenLayers

多视图叠加通常会用到Canvas里的saveLayer方法,这个方法在实现一些特定的效果(比如半透明)时非常有用,但由于其底层实现会在GPU渲染上涉及多图层的反复绘制,因此会带来较大的性能问题。

checkerboardRasterCacheImages

从资源的角度看,另一类非常消耗性能的操作是渲染图像,因为图像渲染会涉及I/O、GPU存储以及不同通道的数据格式转换,因此渲染过程的构建需要消耗大量资源。

UI线程问题定位

如果说GPU线程问题定位的是渲染引擎底层渲染异常,那么UI线程问题发现的则是应用的性能瓶颈。比如在视图构建时,在build方法中使用了一些复杂的运算,或是在主Isolate中进行了同步的I/O操作。这些问题,都会明显增加CPU的处理时间,拖慢应用的响应速度。

针对这类问题,我们可以使用Flutter提供的Performance工具,来记录应用的执行轨迹。Performance是一个强大的性能分析工具,能够以时间轴的方式展示CPU的调用栈和执行时间,去检查代码中可疑的方法调用。

总结

在Flutter中,性能分析过程可以分为GPU线程问题定位和UI线程(CPU)问题定位,而它们都需要在真机上以分析模式(Profile)启动应用,并通过性能图层分析大致的渲染问题范围。

总的来说,由于Flutter采用基于声明式的UI设计理念,以数据驱动渲染,并采用Widget->Element->RenderObject三层结构,屏蔽了无谓的界面刷新,能够保证绝大多数情况下我们构建的应用都是高性能的。

性能优化建议

  • 控制build方法耗时,将Widget拆小,避免直接返回一个巨大的Widget
  • 尽量不要为Widget设置半透明效果,而是考虑用图片的形式代替
  • 对列表采用懒加载而不是直接一次性创建所有的子Widget

对于iOS开发者来说,在完成性能优化后,使用AppUploader这样的工具可以简化应用打包和上传流程,让开发者能够更专注于应用质量本身。