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盲盒。
目录
相关文章
|
26天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
105 4
|
27天前
|
缓存 监控 前端开发
优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面
本文探讨了优化 Flutter 应用启动速度的策略,涵盖理解启动过程、资源加载优化、减少初始化工作、界面布局优化、异步初始化、预加载关键数据、性能监控与分析等方面,并通过案例分析展示了具体措施和效果,强调了持续优化的重要性及未来优化方向。
54 10
|
26天前
|
前端开发 数据处理 开发者
Flutter应用开发中滚动性能优化与无限列表实现的重要性
本文深入探讨了Flutter应用开发中滚动性能优化与无限列表实现的重要性。首先分析了影响滚动性能的因素,如布局复杂度、重绘频率和数据处理等。接着介绍了优化方法,包括懒加载、简化布局、控制重绘和高效数据处理。最后详细讲解了无限列表的实现原理及步骤,并通过案例分析展示了具体应用,旨在为开发者提供实用的技术指导。
36 5
|
2月前
|
前端开发 JavaScript Android开发
Flutter 与 React Native - 详细深入对比分析(2024 年)
Flutter和React Native是两大跨平台框架,各有优缺点。Flutter性能优越,UI灵活,使用Dart;React Native生态广泛,适合JavaScript开发。
674 5
Flutter 与 React Native - 详细深入对比分析(2024 年)
|
1月前
|
缓存 JavaScript API
Flutter&鸿蒙next 状态管理框架对比分析
在 Flutter 开发中,状态管理至关重要,直接影响应用的性能和可维护性。本文对比分析了常见的状态管理框架,包括 setState()、InheritedWidget、Provider、Riverpod、Bloc 和 GetX,详细介绍了它们的优缺点及适用场景,并提供了 Provider 的示例代码。选择合适的状态管理框架需考虑应用复杂度、团队熟悉程度和性能要求。
109 0
|
7月前
|
Web App开发 缓存 前端开发
【Flutter前端技术开发专栏】Flutter中的性能优化与内存管理
【4月更文挑战第30天】本文探讨了Flutter应用的性能优化和内存管理。关键点包括:减少布局重绘(使用`const`构造函数和最小化依赖),选择合适的动画实现,懒加载和按需加载以提升性能。同时,强调了避免内存泄漏和优化内存使用,利用Flutter提供的性能分析工具。实践案例展示了如何优化ListView,包括使用`ListView.builder`和缓存策略。通过这些方法,开发者可以提升应用的响应性、流畅性和稳定性。
280 0
【Flutter前端技术开发专栏】Flutter中的性能优化与内存管理
|
4月前
|
开发框架 Dart 前端开发
移动应用开发中的跨平台策略:React Native与Flutter的比较分析
【8月更文挑战第31天】 在快速变化的移动应用市场,开发者面临着如何在众多平台间高效部署应用的挑战。本文将深入探讨两种主流的跨平台移动应用开发框架——React Native和Flutter,通过对比它们的核心特性、性能表现以及社区生态,为开发者提供选择框架时的参考依据。我们将借助代码示例,展现两者在实际开发中的应用差异,并分析各自的优势和潜在局限,以期帮助开发者根据项目需求做出明智的技术选型。
|
6月前
|
移动开发 Dart 前端开发
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
深度分析:React Native、Flutter、UniApp、Taro、Vue的差异
465 6
|
7月前
|
存储 缓存 监控
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
【4月更文挑战第30天】本文探讨了Flutter中优化列表滚动性能的策略。建议使用`ListView.builder`以节省内存,避免一次性渲染所有列表项。为防止列表项重建,可使用`UniqueKey`或`ObjectKey`。缓存已渲染项、减少不必要的重绘和异步加载大数据集也是关键。此外,选择轻量级组件,如`StatelessWidget`,并利用Flutter DevTools监控性能以识别和解决瓶颈。持续测试和调整以提升用户体验。
223 0
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
|
7月前
|
前端开发 数据处理
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现
【4月更文挑战第30天】本文探讨了 Flutter 中的滚动性能优化和无限列表实现。关键点包括:1) 滚动性能直接影响用户满意度,优化可提升响应速度;2) 影响因素有布局复杂度、频繁重绘和数据处理;3) 优化措施包括懒加载、简化布局、减少不必要的重绘和高效处理数据;4) 无限列表通过监听滚动位置,动态加载新数据;5) 实现时注意加载策略、数据处理效率和内存管理。案例分析和总结强调了优化在实际开发中的重要性。
144 0
【Flutter 前端技术开发专栏】Flutter 中的滚动性能优化与无限列表实现