作者:shizhengtao,华为性能调优工具专家
应用的性能优化一直以来都是开发者所面临的一大难题,在2023HDC大会上全新亮相的HarmonyOS NEXT开发者预览版,其中鸿蒙开发套件DevEco Profiler,对应用卡顿这一问题的定位解决又提供了哪些能力呢?本文带你一探究竟。
一Realtime Monitor,高效发现卡顿问题
Realtime Monitor实时监测应用运行过程中的一系列性能指标,并以可视化面板展示这些指标。开发者使用十分简单,只需在DevEco Profiler工具界面的左上角选择好您要观测的应用进程,这一功能即会自动打开。
图一 Realtime Monitor
在Realtime Monitor中,您可以看到如下指标项:
①系统性能事件:借助HarmonyOS NEXT自带的性能检测能力,帮助您自动地发现一些与性能、稳定性相关的运行事件。
②系统异常事件:借助HarmonyOS NEXT自带的异常检测能力,帮助您自动地发现一些异常的运行事件。
③前台Ability:检测应用当前在前台显示的UIAbility,当发现异常指标时,您能够快速获知是在哪个UIAbility运行时产生的。
④CPU使用率:检测应用的CPU使用率和系统整体的CPU负载,持续过高的CPU占用往往会带来能耗过高的问题,是需要重点关注的。
⑤内存使用量:检测应用的内存使用量和系统整体的内存负载,如果出现应用内存周期性上涨的情况,很可能有内存泄漏产生了,需要重点关注。
⑥设备FPS:检测设备当前的FPS帧率,当应用界面静止而FPS很高时可能存在过度渲染问题,当应用界面变化大而FPS不高时则可能存在丢帧问题,也就是前面提到的流畅性问题。
⑦设备GPU利用率:检测设备当前的GPU利用率,当FPS帧率不够时,通过GPU利用率和CPU利用率指标的对比,即可做一个初步的定界:瓶颈是在GPU侧还是在CPU侧。
⑧器件能耗:检测应用使用各个物理器件的耗电量和总耗电量,帮助您快速分析应用当前的耗能分布情况。
借助这些实时的性能指标,您可以快速了解应用进程的运行性能,这样就能在应用产生某些性能问题时快速的发现和定界。
二 场景化分析,直击问题源码行
在DevEco Profiler工具的设计之初,我们便确定了一条核心理念,就是要提供场景化的低门槛调优工具,构建Top-Down式的UX交互设计,引导开发者分析性能数据时能够做到抽丝剥茧、层层递进,而不是一开始便直接陷入到数据海洋的细节之中。这在性能调优领域是十分重要的,我们希望将每一类性能问题背后的故障模型,通过界面设计直观地体现给开发者们。开发者们能够在拿到性能数据的第一时间,便完成对问题的初步定界和判断,然后有的放矢的去分析抓取到的数据,清晰的解决思路是解决性能问题的必备条件之一。除此之外还有极为重要的另一点则是,所有场景我们都希望能帮助开发者直接定位到问题代码行,通过工具定位到瓶颈函数后,可以直接双击函数栈帧,就可以快速在DevEco Studio的编辑器中打开相关源文件,开发者们可以马上进行分析优化。
在8月份HDC大会亮相的DevEco Profiler中,除了已经发布的用于函数热点和内存分析相关的基础调优模板之外,今年为各位开发者们带来了真正体现场景化这一理念的两大高级模板:Launch Insight和Frame Insight。
Launch Insight:全面拆解应用冷启动过程,抓取不同阶段的耗时数据,帮助开发者快速分析冷启动过程的耗时瓶颈。
Frame Insight:记录每一帧的渲染数据,自动标识其中的卡顿帧,并提供同时段的系统Trace信息和函数栈采样数据,帮助开发者高效分析卡顿位置和原因。
接下来,让我们一探Frame模板究竟,看看它到底是如何帮助开发者有的放矢、抽丝剥茧地分析丢帧问题的。
三 Frame Insight,高效定位卡顿问题
上一节我们提过,会将性能问题背后的故障模型直观地体现给开发者,因此在介绍Frame模板之前,首先需要各位开发者们先简单了解一下,在HarmonyOS NEXT中图形渲染的流程是怎样的,如果出现卡顿其可能的阶段和原因是什么。
在HarmonyOS NEXT中,图形系统采用了统一渲染的模式,遵循着一个典型的流水线模式,以60Hz刷新率为例,整个过程如下图二所示,如果是90Hz,每个Vsync的周期就是11.1ms了。
图二 60Hz刷新率渲染流程
在整个渲染流程中,首先是由应用侧响应消费者的屏幕点击等输入事件,由应用侧处理完成后再提交给Render Service,由Render Service协调GPU等资源处理后,在将最终的图像统一送到屏幕上进行显示。聪明的读者想必这个时候已经可以由这个流程推导出相应的故障模式了,就像图三图四所示。
图三 应用卡顿导致丢帧的故障模型
图四 Render Service卡顿导致丢帧的故障模型
在整个处理流程中,应用侧和Render Service侧都有可能出现卡顿导致最终用户观测到丢帧的可能,我们分别将这两种情况命名为了AppDeadlineMissed和RenderDeadlineMissed。一般而言,前者可能是应用逻辑处理代码不够高效导致的,后者可能是界面结构过于复杂或者GPU负载过大等原因导致的。这两个故障模型通过我们的Frame模板都可以直观地看到。补充好这些预备知识后,接下来,让我们进入正题。
首先是模板的选择和录制,这一步骤是很简单的。开发者们只需要点几下鼠标,然后在录制期间复现卡顿丢帧场景即可。整个过程如图五所示,在录制期间,DevEco Profiler会使用HarmonyOS NEXT中丰富的DFX工具,自动地为开发者们采集丢帧场景下所需的各类性能数据,录制解析完成之后,就可以展开分析了。
图五 Frame模板录制解析
在录制完成后,您可以观测到一系列数据泳道,如图六所示。
图六 Frame模板数据泳道
①Frame泳道:直观呈现丢帧故障模型对应的性能数据,帮助开发者快速定位到出现卡顿丢帧的时段,并且能够对丢帧原因做一个初步判断。
②ArkTS Callstack泳道:抓取和呈现ArkTS的函数热点,帮助开发者定位ArkTS侧的耗时瓶颈。
③Native Callstack泳道:抓取和呈现Native C++的函数热点,帮助开发者定位Native侧的耗时瓶颈。
④CPU Core泳道:抓取和呈现各个CPU核心的运行细节,帮助开发者定位线程优先级、系统调度等带来的性能问题以及线程实际运行的细节。
⑤System Trace泳道:抓取和呈现各个进程的system trace和user trace,帮助开发者了解查看系统的运行细节,和某些核心任务的准确运行时间。在分析丢帧问题时,首先可以聚焦展开第一条Frame泳道。在这条泳道中,我们抓取了图形渲染过程的一些关键节点信息,并将其可视化了出来,如图七所示。
图七 Frame泳道
①应用帧处理:为您显示了应用侧每一帧的处理耗时,方块的长度即为具体的耗时,绿色的即为在预定周期内完成的帧,红色的则是没有在预定周期内完成的帧
②RenderService帧处理:为您显示了Render Service侧每一帧的处理耗时,条块显示逻辑同应用侧
③提交关系:通过连线的方式,将应用侧提交的帧和Render Service侧接收处理的帧关联起来,并且标有相应标号,您可以立刻观测到这个应用到系统的渲染流程
④期望开始和结束处理时间:通过两根竖线标记了被选择帧,期望开始处理和期望完成处理的时间,一旦超时,您可以借助这两根竖线,去观测同一时间的其他性能数据
⑤详细数据:为您提供被选择的帧的详细数据,通过Corresponding Slice或Preceding Flows的跳转按钮,您可以快速找到对应的详细system trace做进一步分析通过这一条泳道,开发者们可以快速发现丢帧的位置,并完成初步的定界:如果是应用帧处理有红色出现,那需要进一步审视在UI线程中的处理逻辑,是否过于复杂或低效,又或者是被别的什么任务抢占了资源;如果是RenderService帧处理有红色出现,那需要审视是否是界面布局过于复杂。后者可以借助DevEco Studio内的ArkUI Inspector等工具进一步分析,本文不做过多阐述。针对前一种现象我们继续分析。
在找到了处理超时的帧之后,开发者们可以有两种选择,一种是分析system trace,另一种则是分析采样得到的函数热点。前一种方式需要对整个系统和关键的trace点有深入的了解,对于现阶段的开发者们可能还有些困难,所以我们还是建议开发者们直接分析函数热点。分析的方式很简单,找到ArkTS Callstack泳道,框选一下即可。这里有一个小技巧,开发者们可以点击泳道信息区的收藏按钮,将应用帧处理的泳道收藏置顶,如图八所示,可以有效防止上下文信息丢失。
图八 置顶收藏关键泳道
将ArkTS Callstack泳道中红色帧的时段框选起来之后,就可以在下方详情面板中查看到这段时间的函数热点了。我们提供了两种函数热点展现形式供开发者选择,一种是Top-Down形式的一个树状列表,如图九所示;另一种则是许多开发者可能更耳熟能详的火焰图,如图十所示。开发者们可以选择自己习惯的方式去查看。一般来说,如果所选的时间段里,函数栈比较复杂的话,用火焰图找热点会更高效。在这两种形式之外,我们还提供了一个自动查找瓶颈路径的能力,也就是显示在图九和十右侧的部分。当您在左侧Top-Down或火焰图中点击某个具体的函数栈帧结点后,我们会为您计算找到从这个节点往下,最耗时的那条调用路径,当您点击这条调用路径上的函数栈帧时,左侧的图表也会自动展开或聚焦到对应结点上,为您提升瓶颈定位效率。
图九 函数热点Top-Down视图
图十 函数热点火焰图
当锁定到某个热点函数之后,只需要双击函数结点,Profiler工具就会为您自动打开对应的源文件,并Focus到相应代码行。当然了,这里有一个前提,这个源文件须是属于当前工程,并且是在DevEco Studio内完成编译的。
四 验证和迭代优化
通过前述步骤,开发者们应当已经能够定位到瓶颈代码了,但是任务到此还远未结束。您还需要在优化完成后,再次使用工具的前几项能力来验证,一般而言性能优化并不是一件一蹴而就的事,需要循序渐进逐步改进。这需要经验,但更需要耐心,每一次卡顿都很可能是多个子问题共同叠加导致的。这也是性能优化这个任务,往往需要团队内的大牛来进行的原因之一。
当然了,这其实也给我们这些程序员指明了一条升职加薪之路,学会调优,去解决性能问题这种难题,解的多了,自然就成为团队技术骨干了,也希望这篇文章和我们的调优工具DevEco Profiler能为各位开发者的晋升之路带来一些帮助,感谢您的阅读。