如何排查flutter性能问题

Flutter官方提供了Flutter DevTools和一些IDE Flutter plugin来辅助开发者进行性能评测,除了这些工具以外,还可以借助Dart和skia引擎提供的工具进行性能分析和调试。这里简单介绍下,Dart的Observatory和Skp Debugger的使用。

0x01 Observatory

Observatory是Dart VM的性能分析工具,可以借助Observatory对Dart VM进行内存,cpu,线程,渲染流程等方面的分析,在进行页面绘制性能分析时,可借助Observatory的timeline工具进行辅助分析。可以通过以下两种方式打开Observatory URL的Web页面。更详细信息可以查看官方文档:
https://flutterchina.club/debugging/
https://dart.cn/tools/dart-devtools

1.通过flutter run打开Observatory

可以使用flutter run --profile | grep 127命令可以看到,在终端中包含了观测台的地址
image.png

2. 通过Android Studio打开Observatory

1.通过点击Android studio底部的工具栏图标,打开Devtools

image.png

2.在截取浏览器中显示的uri参数

image.png

3.借助urldecode工具解码,两次decode后就是Observatory本地服务地址。

image.png

0x02. Observatory Timeline

1. Flutter debug flag

Flutter提供了很多debug flag用来帮助开发者跟踪不同处理流程的执行过程,需要注意的是,所有debug开头的flag只有在debug模式下才会生效,如

  • debugProfileBuildsEnable:向Timeline事件中添加每个widget的build信息
  • debugProfileLayoutEnabled:向Timeline事件中添加每个renderObject的layout信息
  • debugProfilePaintEnabled: 向Timeline事件中添加每个renderObject的paint信息
  • debugPaintLayerBoadersEnabled: 来用为每个layer的边界显示橙色边框
  • debugPrintRebuildDirtyWidgets:打印标记为dirty的widgets
  • debugPrintBeginFrameBanner/debugPrintEndFrameBanner:打印每帧开始和结束

最简单的方式是在程序顶部入口void main()中设置它,如下案例代码所示:
image.png
这样我们就可以在Observatory的Timeline中查看widget build在每一帧中的调用和耗时情况
image.png

2. 自定义Timeline跟踪

要执行自定义性能跟踪和测量Dart任意代码段的wall/CPU时间(类似于在Android上使用systrace)。 使用dart:developer的Timeline工具来包含你想测试的代码块,例如:

1
2
3
Timeline.startSync('interesting function');
// iWonderHowLongThisTakes();
Timeline.finishSync();

这段代码等同于Android原生端的beginSection和endSection

1
2
3
Trace.beginSection("");
// xxxxx
Trace.endSection();

然后打开你应用程序的Observatory timeline页面,在”Recorded Streams”中选择’Dart’复选框,并执行你想测量的功能。刷新页面将在Chrome的跟踪工具中显示应用按时间顺序排列的timeline记录。

3. 使用Observatory查看skia绘图指令

使用命令:flutter run --profile --trace-skia
重点关注saveLayer和clipPath函数的调用

0x03. skpdebugger

通过抓取skp,回放每条skia绘图指令的执行过程,可以在屏幕上直观的看到绘制流程的每个步骤,单步分析每一条绘图指令,从而定位在单帧绘制中影响绘制效率的问题。
点击查看【bilibili】

使用步骤:

  1. 使用flutter screenshot --type=skia --observatory-uri=uri命令,抓取一帧skia绘图指令的执行过程,截取skp可以单步检测每条绘图指令
  2. 将生成的skp文件上传https://debugger.skia.org/

    注意:

    Android Studio4.1版本更改了插件的安装路径,在Flutter1.23以下,flutter doctor命令可能会找不到AS的flutter&Dart plugin,导致flutter screenshot命令执行失败,这里可使用以下命令解决:
    ln -s ~/Library/Application\ Support/Google/AndroidStudio4.1/plugins ~/Library/Application\ Support/AndroidStudio4.1

0x04 总结

  1. profile模式是最接近release的性能表现,当需要获取flutter app较为真实的性能评测数据时,要使用profile进行测试。而需要对具体的build paint流程进行详细分析时使用debug模式进行trace
  2. 使用真机,不要使用模拟器,尤其是不要使用iOS的模拟器,模拟器没有硬件加速,所以在模拟器的测试数据和真机的差别会很大
  3. skpdebugger是神器,通过对单帧绘制指令的采集,可以很清晰的看到在绘制中不合理的部分。针对不合理的绘制进行单帧绘制优化
  4. 重点关注saveLayer和clipPath的调用

参考文档

https://www.sunmoonblog.com/2020/01/10/flutter-performance-tools/
https://cloud.tencent.com/developer/article/1591997
https://flutterchina.club/debugging/
https://flutter.cn/docs/testing/code-debugging