Flutter性能优化分析

简介: 使用工具来分析Flutter的性能瓶颈

使用DevTools来调试

# 统计Flutter应用启动时间
flutter run --trace-startup --profile
# 运行profile模式
flutter run --profile --trace-skia 
#example
fvm flutter run --profile --trace-skia -d 00008101-000318213A84001E
Flutter run key commands.
v Open Flutter DevTools.
s Save a screenshot to flutter.png.
w Dump widget hierarchy to the console.                                               (debugDumpApp)
t Dump rendering tree to the console.                                          (debugDumpRenderTree)
S Dump accessibility tree in traversal order.                                   (debugDumpSemantics)
U Dump accessibility tree in inverse hit test order.                            (debugDumpSemantics)
P Toggle performance overlay.                                    (WidgetsApp.showPerformanceOverlay)
a Toggle timeline events for all widget build methods.                    (debugProfileWidgetBuilds)
M Write SkSL shaders to a unique file in the project directory.
h Repeat this help message.
c Clear the screen
q Quit (terminate the application on the device).
An Observatory debugger and profiler on Junhua’s iPhone 12 Max is available at: http://127.0.0.1:50356/k7Mnu3QtEnI=/
The Flutter DevTools debugger and profiler on Junhua’s iPhone 12 Max is available at: http://127.0.0.1:9102?uri=http://127.0.0.1:50356/k7Mnu3QtEnI=/

使用DevTools的Timeline可以看到渲染的耗时情况,红色为慢渲染的动作。

分析Skia运行情况

首先运行DevTools,再生成SKP文件,将文件放入SkiaDebugger中进行解析。

传送门:相关文档

# 运行profile模式
flutter run --profile --trace-skia 
# example
fvm flutter run --profile --trace-skia -d 00008101-000318213A84001E
fvm flutter run --profile --trace-skia -d e439ed0f

# 生成SKP文件
flutter screenshot --type=skia --observatory-url=<uri>
# example
fvm flutter screenshot --type=skia --observatory-url=http://127.0.0.1:58856/saNCml2ec4g=/

Screenshot written to flutter_01.skp (34704kB).

SkiaDebugger使用

Flutter将一帧录制成SkPicture(skp)送给Skia进行渲染。捕捉skp,可以进一步分析每一个绘图指令。

GPU相关信息

img

  1. 动作右侧的彩色数字为GPU operation id,多个命令共享一个id时,他们将被处理在一起。
  2. Display GPU Op Bounds将显示一个彩色的矩阵,表示当前GUP在操作时候的边界。
  3. GPU,表示Skia用哪个硬件进行配置绘制。在wasm调试器中,GPU表示WebGL。关闭后则使用CPU,skia会在内存中绘制平面,再将内存的图片拷贝到HTML的图层上,而不使用GPU。

十字线和断点

img

点击屏幕后会出现十字线,可以通过H(左)L右)J(向下)K(向上)来移动位置。

选择“Break on change”时,命令播放将在任何更改所选像素颜色的命令上暂停。这可用于查找绘制您在查看器中看到的内容的命令。

右侧操作栏

Histogram:点击后隐藏不需要的动作

通过在filter textbox中输入!drawannotation save restore concat setmatrix cliprect可以过滤matrix或clip操作,这些动作不会带来可视化的变化

快捷键

使用“,”与“。”可以逐帧显示操作(页面中有提示)。

列表帧数优化

闲鱼-Flutter 流畅度优化实践总结

渲染过程

1、手指松开时,基于 ScrollDragController.end 计算初始速度;

2、UI Thread 向 Platform Thread 请求 requestFrame,在 Platform Thread 收到 Vsync 信息,则向 UI Thread 调用 beginFrame;

3、UI Thread Animate 阶段触发列表滑动一点距离,同时向 Platform Thread 注册下一帧回调;

4、UI Thread Build Widget,再通过 Flutter 三棵树 Diff 算法生成/更新 RenderObject 树;

5、UI Thread RenderObject 树 Layout、Paint 生成 Scene 对象,最后传递给 Raster Thread 进行绘制上屏;

工具

Flutter BenchMark,分析帧数

DevTools:Timeline、CPU燃焰图

DebugFlags:debug.dart

流畅度检测:无需侵入代码的流畅度检测方案有几种, 既可以通过adb取surfaceflinger数据, 也可以基于VirtualDisplay做图像对比,或者使用官方DevTools。第三方比较成熟的如PerfDog

卡顿排查:DevTools是官方的开发配套工具,非常实用

  1. Performance检测单帧CPU耗时(build、layout、paint)、GPU耗时、Widget Build次数
  2. CPUProfiler 检测方法耗时
  3. Flutter Inspector观察不合理布局
  4. Memory 监控Dart内存情况

脚本测试

检测 Flutter 每帧耗时,需要统计 UI Thread 和 Raster Thread 上的计算耗时。所以 Flutter 优化前后比较,使用 SchedulerBinding.instance.addTimingsCallback 获取每一帧的 UI Thread 和 Raster Thread 的耗时数据。

此外,流畅度性能数值受操作手势、滚动速度影响,所以基于人工操作的测量结果会存在误差。这里使用 WidgetController 控制列表控件 fling。

基于录屏的卡顿测试

闲鱼在 Android 端自研了基于录屏数据的流畅度检测。将手机界面想象成多个画面,通过向系统录屏服务 MediaProjection 注册获取 VirtualDisplay,间隔 16.6 ms读取其中的画面数据(字节数组),这里使用字节数组的 hash 值代表当前画面,当前后 2 次读取的 hash 值不变,则认为发生了卡顿。

线上FPS卡顿监测

在线上场景,闲鱼自研了 Flutter 高可用。基本原理是基于2个事件:

  • ui.window.onBeginFrame 事件

    • engine 通知 Vysnc 信号到来,通知 UI Thread 开始准备下一帧画面构建
    • 触发 SchedulerBinding.handleBeginFrame 回调
  • ui.window.onDrawFrame 事件

    • engine 通知 UI Thread 开始绘制下一帧画面
    • 触发SchedulerBinding.handleDrawFrame 回调

这里我们在 handleBeginFrame 处理之前,记录一帧开始事件,在 handleDrawFrame 之后记录一帧的结束。这里每一帧都需要计算列表控件 offset 值,具体代码实现见右图。在整个累计超过 1s 时,执行一次计算,使用 offset 过滤掉没有发生滚动的场景,使用每一帧的时间计算 fps 值。

卡顿堆栈监测

基本原理是,在 C 层轮询发送信号,比如 5ms 一次,每次信号接收触发 dart UI Thread 堆栈采集,对得到的一系列堆栈进行聚合,连续多次相同堆栈就认为是发生了卡顿,这时这个堆栈就是我们想要的卡顿堆栈。

检测过度渲染

通过复写 WidgetsFlutterBinding 的 buildOwner 方法替换 BuildOwner 对象,进而重写 scheduleBuildFor 方法,实现拦截脏 element。基于脏 element 节点,提取出脏节点的深度、直接子节点的数量、全部子节点的数量。

基于全部子节点数量,在闲鱼详情页,我们定位到“快速提问视图”在滚动过程中,频繁被标脏和全部子节点数量过大。查看代码,定位该视图层级过高,通过将视图下沉到叶子节点,一次标脏 build 节点数量从 255 优化至 43。

调试经验

在观看Flutter 的性能测试和理论后,得出的结论:

  • 触发build的几个方式:setState、inheritedWidget、热更新

  • 辅助工具:

    • debugPrintBeginFrameBanner/debugPrintEndFrameBanne

      • 每帧开始/结束
    • debugPrintScheduleBuildForStacks

      • 为什么被构建
    • debugPrintRebuildDirtyWidgets

      • 什么组件被重新构建了
    • debugProfileBuildsEnabled

      • 在观测台里显示构建树
    • debugDumpLayerTree

      • 查看layer树
    • debugPaintLayerBordersEnabled

      • 查看layer界限
    • debugRepaintRainbowEnabled

      • 被重新绘制的RenderObject
    • debugProfilePaintsEnabled

      • 在观测台里显示绘制树
  • 优化build方式

    • 降低遍历出发点(抽离组件,单独更新)
    • 停止树的遍历(重用同一组件的实例)
  • 提高paint的效率(合理利用RepaintBounda,界限分明)

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
3月前
|
Web App开发 缓存 前端开发
【Flutter前端技术开发专栏】Flutter中的性能优化与内存管理
【4月更文挑战第30天】本文探讨了Flutter应用的性能优化和内存管理。关键点包括:减少布局重绘(使用`const`构造函数和最小化依赖),选择合适的动画实现,懒加载和按需加载以提升性能。同时,强调了避免内存泄漏和优化内存使用,利用Flutter提供的性能分析工具。实践案例展示了如何优化ListView,包括使用`ListView.builder`和缓存策略。通过这些方法,开发者可以提升应用的响应性、流畅性和稳定性。
170 0
【Flutter前端技术开发专栏】Flutter中的性能优化与内存管理
|
2月前
|
移动开发 Dart 前端开发
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
164 6
|
3月前
|
存储 缓存 监控
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
【4月更文挑战第30天】本文探讨了Flutter中优化列表滚动性能的策略。建议使用`ListView.builder`以节省内存,避免一次性渲染所有列表项。为防止列表项重建,可使用`UniqueKey`或`ObjectKey`。缓存已渲染项、减少不必要的重绘和异步加载大数据集也是关键。此外,选择轻量级组件,如`StatelessWidget`,并利用Flutter DevTools监控性能以识别和解决瓶颈。持续测试和调整以提升用户体验。
96 0
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
|
3月前
|
前端开发 数据处理
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
【4月更文挑战第30天】本文探讨了 Flutter 中的滚动性能优化和无限列表实现。关键点包括:1) 滚动性能直接影响用户满意度,优化可提升响应速度;2) 影响因素有布局复杂度、频繁重绘和数据处理;3) 优化措施包括懒加载、简化布局、减少不必要的重绘和高效处理数据;4) 无限列表通过监听滚动位置,动态加载新数据;5) 实现时注意加载策略、数据处理效率和内存管理。案例分析和总结强调了优化在实际开发中的重要性。
61 0
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
|
3月前
|
设计模式 缓存 前端开发
【Flutter前端技术开发专栏】Flutter开发最佳实践与性能优化指南
【4月更文挑战第30天】本文为Flutter开发者提供了最佳实践和性能优化指南。建议采用MVC、Provider/Repository和InheritedWidget设计模式,注重代码结构和状态管理。遵循最佳实践,如避免全局变量,智能使用Stateful和Stateless Widgets,以及利用`const`和`final`。性能优化要点包括减少渲染次数、优化图片资源、异步处理和使用Profile模式分析。通过测试确保应用质量与稳定性,打造高性能、高质
92 0
【Flutter前端技术开发专栏】Flutter开发最佳实践与性能优化指南
|
3月前
|
开发框架 前端开发 JavaScript
【专栏】对比分析两种流行的跨平台开发框架——Flutter和React Native,探讨它们的优势、劣势以及适用场景
【4月更文挑战第27天】本文对比分析了Flutter和React Native两大跨平台移动开发框架。Flutter,由Google推出,以其接近原生的性能、快速启动和流畅滚动受青睐,适合高性能和高度定制的项目。React Native,Facebook维护,依赖JavaScript,虽性能受限,但热重载优势和丰富第三方库使其适合快速迭代的项目。两者都在拓展多平台应用,Flutter在桌面和Web,React Native在Windows。选择框架需考虑项目需求、团队技能和性能效率平衡。
298 1
|
3月前
|
Dart Android开发 开发者
常用框架分析(7)-Flutter
常用框架分析(7)-Flutter
|
3月前
|
JSON Dart UED
Flutter 应用程序性能优化建议
Flutter应用程序默认已经具有良好的性能,因此您只需要避免常见的陷阱,就可以获得出色的性能。 您设计和实现应用程序的用户界面的方式可能会对其运行效率产生重大影响。 本文这些最佳实践建议将帮助您编写性能最佳的Flutter应用程序。
Flutter 应用程序性能优化建议
|
3月前
|
Linux Android开发 iOS开发
Flutter笔记:滑块及其实现分析1
Flutter笔记:滑块及其实现分析1
261 0
|
设计模式 算法 vr&ar
Flutter 基础 | 动画框架分析及其中的设计模式
Flutter 基础 | 动画框架分析及其中的设计模式
144 0