电子说
在QML应用开发过程中,可以使用QML Profiler来查找应用程序中典型性能问题的原因,例如启动慢、响应慢、用户界面不流畅等。
本文主要以QML Profiler工具本身出发,描述如何使用QML Profiler来分析QML应用,记录其常规使用方法。
设置QML Profiler
在QtCreator中,依次打开编辑->Preferences->分析器->QML Profiler:
可以选中“Flush data while profiling”复选框,用于在分析停止时定期刷新数据,这将节省目标设备上的内存,缩短了停止分析和显示数据之间的等待时间。
在“Flush interval”字段中,以毫秒为单位设置刷新间隔。间隔时间越短,刷新数据的频率就越高。间隔越长,目标应用程序中需要缓冲的数据就越多,可能会浪费内存。但是,刷新本身是需要时间的,这可能会影响分析结果的显示。
如果有多个QML引擎,并且希望将所有引擎产生的数据聚合到一个跟踪视图中,那么就选中“ Process data only when process ends”复选框。如果不选中,当一个引擎停止时,分析就停止了。
注:在QtCreator中,一般不用设置QML Profiler,我们直接使用就可以了
使用QML Profiler
在QtCreator中使用QML Profiler分析应用软件,按照以下步骤即可:在已经创建了一个项目工程的前提下,依次点击Analyze -> QML Profiler:
然后会自动编译运行对应的项目工程,QML Profiler在我们的应用软件运行过程中,会出现下图所示的类似信息:
(当程序开始运行后,会自动进行时间计数。如果有输入事件,还会显示对应的事件捕获信息)
分析收集的数据
在QML应用程序退出后,则会在QML Profiler视图中自动显示数据,如下图所示:
上图中,水平为时间轴,该时间轴是监听QML应用软件开始到结束的时间。上方有对应的时刻显示;中间位置则是统计的数据,我们可以用鼠标点击对应的数据区块(可以在信息显示栏中看到对应时间内区块的数据情况)。左侧是事件分类,事件在时间轴视图的以一行或多行显示。可用的事件类型取决于应用程序编译时所使用的Qt版本以及使用的Qt Quick版本。在显示数据时,有如下表所示的事件分类:
事件分类 | 描述 |
---|---|
Pixmap Cache | 以像素为单位显示缓存的pixmap数据的总体数量。此外,显示一个单独的事件,每当加载一张图片,显示与它相关的文件名和大小信息 |
Scene Graph | 显示渲染场景图帧的时间,以及渲染的各个阶段的额外的时间信息 |
Memory Usage | 显示JavaScript内存管理器的块分配。通常,内存管理器会将较大的内存块保存为一块,然后将它们以较小的块分发给应用程序。如果应用程序请求单个内存块超过某个大小,内存管理器将分别分配这些内存块。这两种操作模式以不同颜色的事件显示。第一行显示内存管理器所分配的大内存块的大小;第二行显示所分配内存的实际使用情况,这是应用程序实际请求的JavaScript堆的大小 |
Input Events | 显示鼠标和键盘事件 |
Painting | 显示为每帧绘制场景所花费的时间 |
Animations | 显示活动的动画数量和它们运行的帧率。使用Qt 5.3或更高版本构建的应用程序将显示有关渲染线程动画的信息。然后渲染线程动画显示在单独的行中。 |
Compiling | 显示编译QML文件所花费的时间。 |
Creating | 显示场景中创建元素所花费的时间。在Qt Quick 2中,创建元素组件分为两个阶段:(1)第一个阶段是创建数据结构,包括子元素。(2)第二个阶段表示完成回调机制处理(信号和信号处理机制)。但是,并不是所有元素都触发完成回调。这两个阶段在时间轴中显示为独立的事件。 |
Binding | 显示计算绑定的时间以及计算所需的时间 |
Handling Signal | 显示处理信号的时间以及处理所需的时间。 |
JavaScript | 显示在绑定和信号处理程序后面执行实际JavaScript所花费的时间。它列出了可能用于计算绑定或处理信号的所有JavaScript函数。 |
注:由于QML应用程序在启动创建过程中,组件的创建时间极短(一般都是在微秒级别),然而在时间线视图中所呈现的是所有监听时间内的数据,如下图所示:
所以需要缩小时间轴(按住Ctrl,向上滚动鼠标中键或者用鼠标拖动时间轴)去查看组件创建相关的数据信息。例如下图所示:
(由上图可见,大约需要2.41ms创建完QML的小组件)
从Flame Graph视图分析数据
『Flame Graph』视图显示了关于QML和JavaScript执行情况的更简明的统计信息。在Total Time视图中,水平条显示了相对于所有JavaScript和QML事件的总的运行时间,还显示调用某个函数所花费的总时间,而且嵌套显示了函数调用情况。
在下拉菜单中选择Memory,可以查看各函数分配的内存总量
如果要查看函数分配的内存数量,就需要选中下拉菜单中的Allocations一栏。如下图所示:
(这张图可以“从下往上”看,越往上就是QML中的最小元素了。点击视图中的某一项同时会跳转到在代码中的对应行上。)
注:使用鼠标左键双击视图中的项目可以放大对应视图。双击视图中的空白区域可以再次缩小。
与『Timeline』视图不同,在没有QML或JavaScript运行的时候,『Flame Graph』视图不显示时间跨度,因此,『Flame Graph』不适合分析QML应用中每帧的执行时间(『Timeline』视图更适合)。但是,该视图可以很清晰的看到在QML应用程序运行过程中,各种QML和JavaScript事件的总体情况。
从Statistics视图分析数据
『Statistics』视图显示了QML应用中binding、create、compile、JavaScript或信号事件被触发的次数,以及花费的平均时间,如下图所示:
这可以让我们检查需要优化的事件,如果某事件大量出现可能表明触发了不必要的事件。要查看事件发生的中位数、最长时间和最短时间,可以在上下文菜单中选择扩展事件统计。
接着数据显示将如下图所示:
Caller和Callee一栏显示了事件之间的依赖关系,用于检查应用程序的内部功能。Caller一栏表示触发绑定的QML事件,通过Caller我们可以知道是什么触发了绑定中的更改。Callee表示绑定触发的QML事件,从Callee我们可以知道如果更改绑定,哪些QML事件将会受到影响。
结尾
在QML应用程序中,出现启动慢、响应慢、用户界面不流畅等性能方面的问题时。典型的原因可能是:在太少的帧中执行了太多的JavaScript。这意味着所有的JavaScript都必须在GUI线程继续运行之前返回(执行完成)。
导致类似性能问题的另一个典型原因是:创建、绘制或更新了不可见项,该操作在GUI线程中需要花费许多的时间。
在QML Profiler分析视图中,为了发现过度使用JavaScript,应检查Animations和Scene Graph事件中的帧率,寻找间隙,并检查应用程序是否如预期的那样运行。对于JavaScript类别显示函数的运行时间,应该尽量将其控制在每帧16毫秒以下(注:官方文档给出的参数)。
要发现如果是不可见项引起的性能问题,需要查找丢失的帧,并检查是否在应用程序代码中使用了太多的短绑定或每帧都要更新的信号处理程序。除此之外,我们还可以可视化场景图,并找到不可见的项目,因为这些项目往往位于屏幕外或隐藏在其他可见元素之下,稍不留神就溜了。
本文主要描述了如何使用QML Profiler来分析应用程序,更多的内容是从工具本身出发的。如果后续遇着QML应用软件设计上的严重性能问题时,在写写啦。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !