0x00 前言
PerformanceOverlay是在app上显示性能统计数据的浮窗。PerformanceOverlay是一个Widget,有几个属性,用于控制开启哪些功能。
0x01 PerformanceOverlay 分析
PerformanceOverlay的源码是:
~/flutter/packages/flutter/lib/src/widgets/performance_overlay.dart
复制代码
可以看出PerformanceOverlay有以下的属性:
-
final int optionsMask
:用于标记哪些功能打开的flag,有四个标志位,displayRasterizerStatistics :显示光栅化器统计信息(GPU) visualizeRasterizerStatistics :可视化光栅化器统计信息(GPU) displayEngineStatistics :显示引擎统计(CPU) visualizeEngineStatistics :可视化引擎统计(CPU)
final int rasterizerThreshold
: 光栅化的阈值,用于捕获SkPicture跟踪以进行进一步分析,它的值代表每隔几帧捕获一次,默认是0,代表功能是关闭的final bool checkerboardRasterCacheImages
:检查缓存图片的情况final bool checkerboardOffscreenLayers
:检查不必要的setlayer
0x02 启用 PerformanceOverlay
开启Performance Overlay的方法有三种:
1、 Flutter Inspector
Flutter Inspector是一个强大的工具,Performance Overlay的功能也集成在Flutter Inspector里。
需要我们运行Flutter APP后才可以使用,
- 在Android Studio里
选择 View > Tool Windows > Flutter Inspector,就可以打开Flutter Inspector,可以看到有很多功能,如下图:
然后选择Performance Overlay。
- 在VS Code里
通过 View > Command Palette 或者 cmd+p
打开命令板,输入“performance” 然后选择 Toggle Performance Overlay 就行。
2. 使用代码设置
我们知道PerformanceOverlay是一个widget,PerformanceOverlay是在WidgetsApp里被使用的,MaterialApp又使用了WidgetsApp,所以我们通过给MaterialApp 或者 WidgetsApp 设置参数来控制PerformanceOverlay的功能。
所以为了,开启将PerformanceOverlay,要将MaterialApp 或者 WidgetsApp 的showPerformanceOverlay 属性设置为true,如下:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
showPerformanceOverlay: true,
title: 'My Awesome App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'My Awesome App'),
);
}
}
复制代码
0x03 PerformanceOverlay:GPU、CPU统计信息
如下图:
这个浮窗有两个图形:
-
上面的是GPU thread
表示在GPU线程上生成每帧需要的时间。
-
下面的UI thread
表示在UI线程上生成每帧需要的时间。
-
纵轴
图中的纵轴代表时间,每个图形都被分成三格,每小隔代表16ms,如果图中超过这三条线之一,那么您的运行频率低于60Hz。
-
横轴
横轴代表帧。 该图仅在应用程序绘制时更新,因此如果它处于空闲状态,该图将停止移动。每个图形绘制的都是该线程最后300帧的数据。
为了保证60FPS,每帧耗费的时间应该是小于16ms的,看上图中绿色的粗线条,代表的是当前帧的数据,如果当前帧的数据符合预期(<16ms),那么就是绿色的,如果不符合,就是红色的,如下图:
遇到红色的就需要去具体分析,因为会造成APP卡顿:
-
如果GPU thread是红色的
那么可能是绘制的图形过于复杂,或者是执行了过多的GPU操作。
-
如果UI thread是红色的
说明肯定是Dart代码里有耗时操作,导致阻塞了UI操作。
如果两个都是红色的 建议从UI thread,也就是Dart代码查起。
0x03 GPU问题定位
辅助定位GPU问题的,就是PerformanceOverlay的下面两个功能:
-
PerformanceOverlay:checkerboardRasterCacheImages -- 检查缓存图片的情况
还有一个拖慢GPU渲染速度的是没有给静态图像做缓存,导致每次build都会重新绘制。我们可以把静态图像加到RepaintBoundry中,引擎会自动判断图像是否复杂到需要repaint boundary。
-
PerformanceOverlay:checkerboardOffscreenLayers -- 检查不必要的setlayer
setlayer是Canvas里的操作,非常耗性能,所以要尽量避免这个操作。你可能会好奇,我根本没用到这个,是的,我们一般是不会使用这个函数的,所以当你开启了这个检查后,会发现啥也没有,正好说明了你没有用到setlayer。我们一般都是被动的使用,比如需要剪切、透明的操作,用到一些widget的时候,这些widget会用到setlayer方法,一旦遇到这种情况,我们要想一下是否一定要这么做,能不能通过其他方式实现。
开启这两个功能的方法:
MaterialApp(
showPerformanceOverlay: true,
checkerboardOffscreenLayers: true, //使用了saveLayer的图像会显示为棋盘格式并随着页面刷新而闪烁
checkerboardRasterCacheImages: true, // 做了缓存的静态图像图片在刷新页面使不会改变棋盘格的颜色;如果棋盘格颜色变了,说明被重新缓存,这是我们要避免的
...
);
复制代码
0x04 GPU优化 tip
- 一些效果尽量设置在子Widget上,而不是父Widget
例如,要实现一个混合图层的半透明效果,如果把透明度设置在顶层Widget上,CPU会把每个子Widget的图层渲染出来,在执行saveLayer
操作保存为一个图层,最后给这个图层设置透明度,但是saveLayer
的开销很大,所以官方给出建议:首先确认这些效果是否真的有必要;如果有必要,应该把透明度设置到每个子Widget上,而不是父Widget。裁剪操作也是类似。
0x05 UI问题定位
可以使用 Observatory里的timeline的功能分析。
作者:小德_Kurt
链接:https://juejin.im/post/5c4d3ef66fb9a049b13e95b7
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。