给你们介绍DevTools
的主要缘由主要有几点 🚀 :git
DevTools
自己是Flutter
官方推荐的一个调试工具。DevTools
是用Flutter
编写的,极具特点 🖼 。首先,隆重介绍今天的主角:DevTools 👏web
官网介绍:
DevTools is a suite of performance and debugging tools for Dart and Flutter. It’s currently in beta release, but is under active development.
编程翻译:
DevTools
是Dart
和Flutter
的一套性能和调试工具。它目前处于测试版,但正在积极开发中。后端
要使用DevTools
首先,全部的一切的前提,确定是,装上它,yes
,这看似简单的一步其实花了我还蛮久时间的。但愿各位安装顺利,我将给各位介绍四种打开DevTools的方法
。浏览器
使用以上两种开发工具的小伙伴看这边了 🙋♂️,在此类开发工具上打开DevTools
一共分三个步骤markdown
Flutter
插件:首先确认你已经在开发工具内安装了Flutter
插件(不会有人还没装吧,不会吧 👀 )
app
对,就是字面意思,容许你要调试的那个项目工程(推荐使用Profile
模式)。友情提示:Profile
模式只能在真机 📱 上运行。异步
DevTools
的入口其实 DevTools
的入口不是很显眼,可是还算好找,在底部的工具栏,我们常常用的hot reload
边上,直接点击该按钮 🔘 就能够启动该项目的DevTools
。
函数
(PS:我本身用的是Android Studio
,可是我并无经过这种方式成功,一直就是Installing DevTools...
,若是各位知道缘由,欢迎在评论区指点一下,阿里嘎多 🤗 )工具
Flutter
插件:首先确认你已经在开发工具内安装了Flutter
、Dart
插件(同Android Studio
)
经过在 VS Code
中打开你的项目的根目录(包含 pubspec.yaml
)并点击 Run > Debugging
(F5
),来开启调试会话。
启动开发程序
VS Code
命令控制板中将会显示 Dart: Open DevTools
DevTools
。若是在你的环境变量 PATH
中有 pub
, 能够运行 🚀:
pub global activate devtools
复制代码
若是环境变量 PATH
中有 flutter
, 能够运行 🚀:
flutter pub global activate devtools
复制代码
下一步,启动本地 web server
服务来运行开发者工具。运行下面两个命令中的一个。
pub global run devtools # If you have `pub` on your path.
复制代码
flutter pub global run devtools # If you have `flutter` on your path.
复制代码
运行这两行代码以后,在命令行应该会有这样一个输出:
An Observatory debugger and profiler on iPhone X is available
at: http://127.0.0.1:50976/Swm0bjIe0ks=/
复制代码
at
后面的就是DevTools
的地址,你们直接用Chrome
打开便可。打开后的网页须要你填写一个连接,也就是你须要调试的项目的Debug service
监听地址,这个地址哪儿来的呢 🤔 ?
3. 启动一个 app
来 debug
其实上面所需的连接 🔗 地址,就在咱们平时运行项目的Log
中。你们运行工程,在日志的前几行就能够找到Debug service
的地址,就是图中 listening on
以后的部分,将该连接填入咱们在第二步打开的网页中,就能够进入到咱们项目对应的DevTools
之中。
以上三种是Flutter
官网提供的安装、打开方式,很惋惜,我都没有打开成功 🤯 ,不是一直安装,就是打开了一个很是老的版本的DevTools
,应该是和个人Dart SDK
路径配置有关,因此通过个人研究,发现了一个很是痛快 🤫 的打开方法(目前暂不知有什么弊端)。
Flutter
文件夹的地址。这个因人而异,各位应该清楚本身电脑上flutter
的路径吧,好比我就放在我的的development
目录下:
/Users/tys/development/flutter
复制代码
DevTools
这就是我这边要说的暴力打开的关键 🔑 ,我发现...,这个DevTools
,好像已经悄悄的放在了Flutter
中。
/Users/tys/development/flutter/.pub-cache/bin/devtools
复制代码
在上面这个目录下,你们能够直接找到它,双击点开,直接好家伙 💡
芜湖~直接到达上面用命令行打开的最后一步。并且这就是你当前使用的Flutter
版本对应的最新的、可用的DevTools
!
我将按照DevTools顶部工具栏的顺序给各位逐个介绍各个功能 🤓 。
1. 了解现有布局。
2. 诊断布局问题。
有关这个模块的内容咱们根据下图中红色标注的顺序一块儿看一下 🔍
这实际上是一个选择视图,你们看到这个Tab
下对应的其实就是你的整个绘制树 🌲 了,这样一颗树的结构复杂度通常都会和你的页面复杂度相关。若是是一个复杂的页面结构,这棵树也会很是庞大,看起来会很模糊,为了让咱们能够更好的看到树里面的细节结构,咱们就能够点击树上的某个节点,区查看树的某一部分的详细内容 🔮 。
顾名思义,其实这里就是咱们刚才所选择的节点的详细信息,其实现实的信息真的能够说很是走心 ❤️ 了。看图中,我选了一个Container
节点 ,Container
下的未赋值属性都给你提示出来了,如bg
背景颜色等。若是你的页面内有颜色、色彩的叠加之类的,经过它能够看的很清晰 🔬 。
这个就厉害了,是你当前选中节点的布局浏览器。好比你们能够看到,我选中的这个Container
下面有包裹的详细结构都有显示出来,包括各个Wiget
的边界,甚至给你显示了计算后的高度和宽度 📏 (按照标准的分辨率尺寸)。
Layout Explorer
不只能让你查看整个布局界面,还可让你作一些简单的动态操做,让你在不改动代码的前提下,明确你的布局问题,或者缺陷(请看动图⬇️ )。
点击该按钮,将下降你App
内的全部动画效果的速度,感觉0.5
倍速的神奇世 🤩 ,这里说的Animations
包括但不只限于你的界面跳转,Hero
等系统级动画,我的认为这部分功能主要有两个做用
1. 若是在该模式下你的动画不存在任何卡顿,则说明你的动画效能很是完美,能够达到比较好的用户体验 👍 。
2. 让部分动画制做者看清本身的动画绘制曲线、路径 🕳 。
在渲染中添加视觉调试提示,以显示边框,填充,对齐和间隔。会在你的模拟器上显示总体的布局状况,这些状况包括你的总体渲染方向和基础组件类。
使每一个RenderBox在其每一个文本基线处绘制一条线。就是下图中的绿线 ⬇️
打开这个功能,你的界面在重绘时,会在重绘的部分更改一个边界颜色 🎆 。好比,你有一个banner
,间隔1s
换一张图片,那么每一秒你的banner
图周边的颜色就会变一个随机颜色。我的感受其目的是让咱们看到当前页面正在绘制或重绘的部分。
在进行性能调试时请使用实际设备调试。Skia有两套很不一样的后端,Flutter在iOS模拟器中使用纯CPU后端,而在实际设备通常使用GPU硬件加速后端,因此性能特性很不同。
TimeLine
是DevTools
中比较实用有实际意义的部分。可让你实际看到你的APP
存在的UI
问题或GPU
问题。接下来我将带各位来学习如何去分析本身Flutter APP
的绘制性能 🩺 。
你们首先能够看到,在上图中最上层的部分是一个柱形图 📊 。这部分是你刚才所作操做的一个绘制状态图,根据右边的图例,也能明白其中的意思,这边我再给各位明确一下。
你们看柱状图中有红色有蓝色,淡蓝色的是UI
线程的绘制状况、深蓝色是你的栅格化线程(GPU
线程)。红色,表明你的绘制出现了卡顿。通常来讲咱们在Flutter
里咱们定义卡顿:若是一帧的渲染时间超过16ms
,则会被认为此帧是延时的,为了达到帧渲染频率到 60 FPS
(每秒帧数),每一帧的渲染时间必须等于或少于 16 ms
。若是没有达到这个目标,你会发现 UI
不流畅或丢帧 📌 。
咱们在整个界面的中间部分能够看到的是Timeline Event
,它其实对应的就是咱们上面绘制状况图的细节状况,是绘制过程当中的事件。咱们利用它能够详细的看见咱们卡顿的缘由。咱们挑选其中卡顿的一帧,来仔细分析一下 🧮 。
在下图中你们能够看到在Timeline Event
中,依然分为了两个部分,上半部分是UI Event
,下半部分是Raster Event
。在这一阵中,咱们能够明显的感受到的是,咱们的UI Event
占用了很是长的时间 ⏰ 。为了你们能对整个TimeLine Event
的含义有更好的理解,这里引用了官方的一段解释:
火焰图选项卡用于显示选中帧事件,
CPU
的样本信息。图表展现的是自上而下的调用堆栈信息,即上面的堆栈帧调用下面的堆栈帧。每个堆栈帧的宽度表明CPU
执行的时长。栈帧消耗CPU
的时间越长,就越洽有多是咱们进行性能改进的好地方。
咱们在上面的堆栈信息中能够看到最上层的一个Event
叫VsyncProgressCallback
,在下图中,咱们能够在底部看到,这个堆栈的耗时高达40.6ms
,几乎是没法接受的🚽 。其实咱们点击一个流畅的帧后,发现其中也会有VsyncProgressCallback
。那么为何这一帧会格外的长,并形成卡顿呢?
所以咱们为了进一步探究其中的缘由,咱们须要进一步的深刻探究,咱们须要更多的信息。
CPU Flame Chart
) 这里有你想要的细节信息,包括内部具体某一个堆栈的耗时状况。为什么VsyncProgressCallback
耗时如此之久。内部有哪些细节操做,这里一清二楚 🐮 。这里咱们能够看到,一个长耗时VsyncProgressCallback
相比一个短耗时的VsyncProgressCallback
多了几个部分。在清楚VsyncProgressCallback
的内部堆栈信息后,咱们就能够有针对性的再对内部的耗时堆栈进行分析。切换到咱们第二个Tab
。
有关
Flutter
中的Vsync
信号推荐阅读: Flutter渲染机制 - UI线程 🔗 。
这部分更贴近咱们开发者,咱们能够详细看到VsyncProgressCallback
具体调用了哪些函数,哪些函数是耗时比较久的。你们再结合上面一张图,咱们在卡顿这一帧多作的工做,或者说多调用的函数,就是这里的performRebuild
,点开函数的具体调用,咱们能够发现,这个函数一直在循环调用。没错这里的performRebuild
其实就是一个遍历你绘制树 🌲 的过程,说明了你在当前帧,更新了一个庞大的绘制树,而且树上的多个子节点也进行了从新绘制。因此咱们应该要排查的就是,咱们在界面中的哪一个部分集中调用了多个组件的重绘,或者哪部分的view_mode
,驱动了这样的一个重绘过程,其中是否有没必要要的重绘。以此来提升渲染性能 😆 。
上面一部分说明了咱们的UI
线程阻塞的部分缘由,和排查方法,那若是是GPU
呢?一样,咱们选取了一帧典型的GPU
耗时操做,在这个堆栈信息中咱们能够看到咱们的GPU
方法确实占用了大量的时间 ⏳ ,一样是GPURasterizer::Draw
为何某一帧会特别久呢?
其实在DevTools
的Raster
视图中,并不能将这部分展现的很是清晰。可是还有一个办法能够深究其缘由。你们能够直接打开以前填入DevTools
的连接。若是你正在profile
模式下运行,你的log
中就能够找到这个连接 🔗 。
点开这个连接,在这个页面的中间部分,咱们能够找到timeline
工具(我已经在图中用红框标出)。
进入这部分timeline
以后,这里就是最最最最详细的每一帧的信息了 📌 。你能够用鼠标选中一块区域,在下方就会输出你选中区域的具体函数调用状况。包括函数名称、总耗时、调用次数、每次耗时以及一个可视化的柱状图 📊 占比状况。一目了然。有关GPU
部分的函数调用须要各位对Flutter Engine
的源码有比较高的理解,才能有针对性的解决问题。其中相关的调用栈很是的复杂。
官方声明的会大量耗时的skia
函数调用:
saveLayer
: 很是耗时,每次调用须要在CPU里从新分配一块绘图缓冲区,而且告诉GPU
切换绘图目标。尤为在比较老的设备上。clipPath
: 耗时,每次调用,会影响接下来每个绘图指令,当绘图指令复杂时,会作屡次和clipPath
的相交操做,把在clipPath
以外的部分剔除。
可能你们会说,这部分函数,平时在编程的时候几乎没有使用 🤯 ,但其实他们普遍存在于咱们常见的Widget
及其属性中。好消息是Flutter Team
在过去的更新迭代中已经剔除了很是多的没必要要的相似上述的耗时操做 🐳 。因此当你们在本身的timeline
中找到相似的耗时操做后,仍是能够经过一些Widget
的组件源码去分析找到出处,相较之前容易得多。
在上图的函数调用状况图中,短耗时的操做不表明其没有可能形成卡顿。有可能你找到了
saveLayer
的调用,但没有想象中的耗时。实际是由于:Skia的GPU的后端在接收到saveLayer
的指令后会进行一个简单的预处理,就当即返回,形成不耗时的假象。但实际后续异步的过程当中还会调用SkCanvas::Flush
形成大量耗时。这里异步处理的目的是将多条预处理消息打包 📦 送至GPU
进行绘制。
有关Flutter
中的界面绘制性能相关就介绍到这里了,但愿这篇文章能给各位起到必定的帮助做用 🤪 ,后续会继续介绍Flutter
相关的内存管理和其余相关知识,敬请期待 🧸 。
参考:DevTools