OpenHarmony实战开发-使用SmartPerf-Host分析应用性能

简介

SmartPerf-Host是一款深入挖掘数据、细粒度展示数据的性能功耗调优工具,可采集CPU调度、频点、进程线程时间片、堆内存、帧率等数据,采集的数据通过泳道图清晰地呈现给开发者,同时通过GUI以可视化的方式进行分析。该工具当前为开发者提供了五个分析模板,分别是帧率分析、CPU/线程调度分析、应用启动分析、TaskPool分析、动效分析。关于工具使用的更多内容可查看SmartPerf-Host调优工具使用指导。

本文提供一些性能分析示例,介绍如何使用帧率分析和应用启动分析两个模板采集数据、分析数据,从而发现性能优化点。

本地部署
使用SmartPerf-Host进行性能分析前,需要先完成本地部署,本地部署的详细指导请参考如何编译TraceStreamer和SmartPerf-Host编译部署指导。在本地部署成功后,可通过https://[部署机器ip地址]:9000/application/访问,如下图。

图1 本地部署访问页

在这里插入图片描述

性能分析示例

FrameTimeline帧率分析
SmartPerf-Host提供FrameTimeline帧率分析功能,可以抓取记录每一帧的渲染数据,自动标识其中的卡顿帧,并提供同时段的系统Trace信息,帮助开发者高效分析卡顿位置和原因。

场景示例
如下场景代码使用了Grid来实现了一个网格布局,在应用界面上下滑动时发现有卡顿掉帧现象。下文基于这个场景来介绍FrameTimeline帧率分析功能的使用方式。

@Entry  
@Component  
struct Index {  @State children: number[] = Array.from<undefined, number>(Array(2000).fill(undefined), (_v: undefined, k) => k);  build() {  Scroll() {  Grid() {  ForEach(this.children, (item: number) => {  GridItem() {  Stack() {  Stack() {  Stack() {  Text(item.toString())  .fontSize(32)  }  }  }  }  }, (item: number) => item.toString())  }  .columnsTemplate('1fr 1fr 1fr 1fr')  .columnsGap(0)  .rowsGap(0)  .size({ width: "100%", height: "100%" })  }  }  
}

抓取数据
下面介绍使用FrameTimeline帧率分析模板抓取数据的步骤:

1.打开Record template -> Trace template -> FrameTimeline模板的配置开关。

图2 FrameTimeline模板配置

在这里插入图片描述

2.自定义配置抓取时间、抓取数据大小和结果文件名称。

图3 抓取配置项

在这里插入图片描述

3.点击右上角Record开始抓取,同时在设备上复现应用掉帧或卡顿的操作过程,抓取完成后页面会自动加载trace数据。

说明:

  • 在数据抓取和分析的过程中,请不要主动退出应用或者设备,否则可能导致分析任务失败。
  • 点击Record时,网站上方出现please kill otherhdc-server!的提醒,表示设备连接失败,说明设备的hdc连接端口被占用,需要在cmd命令行中执行hdckill指令,然后再重新连接设备进行抓取。

分析数据
完整的一个渲染流程,首先是App侧响应用户输入完成UI绘制,然后提交给Render Service,由Render Service协调GPU等资源完成渲染、合成和送显操作,在这个过程中App侧和Render Service侧都有可能出现卡顿最终导致丢帧现象。

通过图4、图5、图6三组泳道数据,开发者们可以快速发现丢帧的位置,并完成初步的定界。

图4 UI + RenderService总耗时

在这里插入图片描述

图5 UI耗时

在这里插入图片描述

图6 RenderService耗时

在这里插入图片描述

  • Expected Timeline是理想帧泳道图,Actual Timeline是真实帧泳道图。
  • 绿色帧为正常帧,橙色帧为卡顿帧,黄色帧表示RS进程与App进程起止异常。
  • UI耗时(图5)显示了应用侧每一帧的处理耗时,方块的长度即为具体的耗时,RenderService耗时(图6)同理。
  • App侧帧/RS侧帧卡顿的计算标准为帧的实际结束时间晚于帧的期望结束时间即为卡顿。
  • App侧有橙色出现,需要审视UI线程的处理逻辑是否过于复杂或低效,以及是否被其它任务抢占资源。
  • RS侧有橙色出现,需要审视界面布局是否过于复杂,可以使用布局检查器ArkUIInspector工具和HiDumper命令行工具辅助分析定位,相关指导可以参考使用HiDumper命令行工具优化性能。

从图5和图6结合来看可以确定场景示例明显属于App侧的帧卡顿。点击卡顿帧进行详细分析,相应的关联帧会通过线连起来,同时在Current Selection显示它的Details信息,如图7。

图7 App卡顿帧

在这里插入图片描述

  • Duration表示帧的持续时间。
  • Jank Type表示卡顿类型。APP Deadline Missed表示应用侧卡顿。
  • FrameTimeLine flows Slice表示链接FrameTimeLine关联帧。
  • Preceding flows Slice表示链接RS关联帧。

如下图,展开的应用泳道图中,存在两个名字和Pid一样的泳道,第一个为线程的使用情况,第二个为线程内的方法栈调用情况。结合卡顿帧对应时间段的Trace数据,可以定位到FlushLayoutTask耗时过长,它的作用是重新测量和布局所有的Item。其中Layout[Gird]耗时最久,因此卡顿原因可以确定为Gird布局处理逻辑过于复杂或低效。

图8 应用布局绘制trace数据

在这里插入图片描述

定位到Grid布局代码段,经过分析,去除了冗余的3层stack容器,并将源数据提前处理为布局中需要的string类型,减少布局消耗。同时给Grid添加cachedCount参数结合LazyForEach进行预加载,cachedCount的值设定为一屏能够渲染的GridItem数量。优化后采用同样的方式抓取数据,得到的FrameTimeline泳道数据如图9,并且滑动过程中无卡顿丢帧现象。

图9 优化后FrameTimeline泳道图

在这里插入图片描述

优化后的示例代码如下:

class MyDataSource implements IDataSource { // LazyForEach的数据源  private list: string[] = [];  constructor(list: string[]) {  this.list = list;  }  totalCount(): number {  return this.list.length;  }  getData(index: number): string {  return this.list[index];  }  registerDataChangeListener(_: DataChangeListener): void {  }  unregisterDataChangeListener(): void {  }  
}  
@Entry  
@Component  
struct Index {  @State children: string[] = Array.from<undefined, string>(Array(2000).fill(undefined), (_v: undefined, k) => k.toString());  @State data: MyDataSource = new MyDataSource(this.children)  build() {  Scroll() {  Grid() {  LazyForEach(this.data, (item: string) => {  GridItem() {  Text(item)  .fontSize(32)  }  }, (item: string) => item)  }  .cachedCount(80)  .columnsTemplate('1fr 1fr 1fr 1fr')  .columnsGap(0)  .rowsGap(0)  .size({ width: "100%", height: "100%" })  }  }  
}

AppStartup应用启动分析

SmartPerf-Host提供了AppStartup功能,以便于分析应用启动时各个阶段耗时情况。应用启动分析功能主要是提供应用启动分析模板,帮助系统调优人员做应用启动慢场景问题分析,快速查找系统侧启动慢阶段和耗时长调用栈信息。

场景示例
以下示例代码展示AppStartup功能。

@Entry  
@Component  
struct Index {  @State private text: string = "hello world";  private count: number = 0;  aboutToAppear() {  this.computeTask();  }  build() {  Column({space: 10}) {  Text(this.text).fontSize(50)  }  .width('100%')  .height('100%')  .padding(10)  }  computeTask() {  this.count = 0;  while (this.count < 10000000) {  this.count++;  }  }  
}

抓取数据
使用如下步骤进行AppStartup数据的抓取:

1.切换到Flags页面,将AppStartup选项切换到Enabled,开启AppStartup模板。

图10 AppStartup特性开关

在这里插入图片描述

切换到Record template页面,点击Trace template,开启AppStartup。

图11 AppStartup模板配置

在这里插入图片描述

Record setting内设置文件名、大小以及抓取时长。

图12 抓取配置项

在这里插入图片描述

4.点击右上角Record开始抓取,同时在设备上打开目标应用。可提前点击StopRecord完成抓取,或者等待时间自动完成抓取。抓取完成后会页面会自动加载trace数据。

图13 停止抓取选项

在这里插入图片描述

分析数据
等待分析结果自动生成。点击右上角的筛选按钮,选中AppStartup,便于查看分析。

图14 模板数据筛选

在这里插入图片描述

展开对应应用的泳道,找到应用启动时的时间段。选中AppStartup泳道全部阶段,可以在下方详情内看到具体阶段的耗时情况。

图15 AppStartup各阶段耗时情况——优化前

在这里插入图片描述

  • ProcessTouchEvent:点击事件输入及处理
  • StartUIAbilityBySCB:处理创建进程信息&创建窗口
  • LoadAbility:拉起进程
  • Application Launching:加载应用
  • UI Ability Launching:加载UI Ability
  • UI Ability OnForeground:应用进入前台
  • First Frame - App Phase:首帧渲染提交-应用
  • First Frame - Render Phase:首帧渲染提交-Render Service

上图展示结果显示,执行耗时最长的是UI Ability OnForeground阶段。目前耗时Duration为323ms。

图16 UI Ability OnForeground阶段耗时——优化前

在这里插入图片描述

在这个阶段里,通过阶段内下方泳道可以发现生命周期aboutToAppear耗时较长,点击该泳道内容可以看到具体耗时Duration,为268ms,占整个UI Ability OnForeground阶段的82%。

图17 aboutToAppear耗时——优化前

在这里插入图片描述

查看代码后发现,在aboutToAppear生命周期函数内执行了耗时的计算任务,导致应用冷启动耗时长。

随后对aboutToAppear内容进行异步延迟处理。优化后代码如下:

@Entry  
@Component  
struct Index {  @State private text: string = "hello world";  private count: number = 0;  aboutToAppear() {  setTimeout(() => {  this.computeTask();  }, 0)  }  build() {  Column({space: 10}) {  Text(this.text).fontSize(10)  }  .width('100%')  .height('100%')  .padding(10)  }  computeTask() {  this.count = 0;  while (this.count < 10000000) {  this.count++;  }  }  
}

处理后用同样的方式获取一遍数据。

图18 AppStartup各阶段耗时情况——优化后

在这里插入图片描述

继续聚焦到aboutToAppear生命周期所在的UI Ability OnForeground阶段,目前耗时Duration为81ms。

图19 UI Ability OnForeground阶段耗时——优化后

在这里插入图片描述

在这个阶段里,通过阶段内下方泳道可以发现需要查看的生命周期aboutToAppear,点击该泳道内容可以看到具体耗时Duration,为2ms,目前只占整个UI Ability OnForeground阶段的2.5%。

图20 aboutToAppear耗时——优化后

在这里插入图片描述

如果大家还没有掌握鸿蒙,现在想要在最短的时间里吃透它,我这边特意整理了《鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程》以及《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

OpenHarmony APP开发教程步骤:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

《鸿蒙开发学习手册》:

如何快速入门:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.基本概念
2.构建第一个ArkTS应用
3.……

在这里插入图片描述

开发基础知识:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙生态应用开发白皮书V2.0PDF:https://docs.qq.com/doc/DZVVBYlhuRkZQZlB3

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/4109.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024第十五届蓝桥杯网络安全赛项WriteUp

欢迎关注公众号【Real返璞归真】回复【蓝桥杯2024】获取完整题目附件。 排名 安全知识 错1个选择题&#xff0c;题目说的不清楚&#xff0c;没搞懂题意。肯定不能用eval。错了理论题有点遗憾。 没想到这题前端是要解析json数据&#xff0c;排除CD选了A&#xff0c;结果发现正…

每日一题(力扣45):跳跃游戏2--贪心

由于题目已经告诉了我们一定可以跳到&#xff0c;所以我们只需去考虑前进最快的方法。即 判断当前下一步能跳的各个位置中&#xff0c;哪个能带你去去向最远的地方&#xff08;why&#xff1f; 因为其他位置所能提供的最大范围都没最远那个大&#xff0c;所以最远的那个已经可以…

嵌入式Linux学习——Ubantu初体验

Ubuntu 和Windows 的最大差别 Windows中的每一个分区都对应着一个盘符&#xff0c;盘符下可以存放目录与文件&#xff0c;而在Ubantu中没有盘符的概念&#xff0c;只有目录结构。实际上不同的目录可能挂载在不同的分区之下&#xff0c;如果想要查看当前目录位于磁盘的哪个分区…

【服务器部署篇】Jenkins配置后端工程自动化部署

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0c;产…

Transformer实战 单词预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;TensorFlow入门实战&#xff5c;第3周&#xff1a;天气识别&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 一、定义模型 from tempfile import Tempor…

ruoyi-nbcio-plus基于vue3的flowable为了适配文件上传改造VForm3的代码记录

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…

java如何使用webService方式调用对接第三方平台

实际使用记录&#xff0c;做个记录&#xff1a; 1、需要对方提供wsdl文件,该文件中有接口的Ip地址&#xff0c;方法名、参数等详细信息&#xff0c; wsdl文档中targetNamespace为命名空间 <xsd:element name"searchBGDMIInfo">标签中name是方法名&#xff1…

数据结构-树和森林之间的转化

从树的二叉链表的定义可知&#xff0c;任何一棵和树对应的二叉树&#xff0c;其根节点的右子树必为空。这里我们举三个树&#xff0c;将这个由三个树组成的森林组成二叉树是这个样子的。 下面我们说明一下详细过程&#xff0c;首先将每个树转化为二叉的状态&#xff0c;如图所示…

NAT网络地址转换实验(华为)

思科设备参考&#xff1a;NAT网络地址转换实验&#xff08;思科&#xff09; 一&#xff0c;技术简介 NAT&#xff08;Network Address Translation&#xff09;&#xff0c;即网络地址转换技术&#xff0c;是一种在现代计算机网络中广泛应用的技术&#xff0c;主要用于有效管…

汇编语言(详解)

汇编语言安装指南 第一步&#xff1a;在github上下载汇编语言的安装包 网址&#xff1a;GitHub - HaiPenglai/bilibili_assembly: B站-汇编语言-pdf、代码、环境等资料B站-汇编语言-pdf、代码、环境等资料. Contribute to HaiPenglai/bilibili_assembly development by creat…

李廉洋:4.27黄金原油下周一行情分析及走势策略。

金价将出现六周来的首次单周下跌&#xff0c;因投资者在金价上涨数月后获利了结。自2月中旬的低点以来&#xff0c;金价已经上涨了约17%&#xff0c;尽管对美联储放松政策的预期正在减弱&#xff0c;但金价仍屡创新高。周五公布的最新通胀数据强化了高利率将暂时维持的观点。“…

MATLAB的几种边缘检测算子(Sobel、Prewitt、Laplacian)

MATLAB的几种边缘检测算子(Sobel、Prewitt、Laplacian) clc;close all;clear all;warning off;%清除变量 rand(seed, 100); randn(seed, 100); format long g;% 读取图像 image imread(lena.png); % 转换为灰度图像 gray_image rgb2gray(image); % 转换为double类型以进行计算…

Git泄露和hg泄露原理理解和题目实操

一.Git泄露 1.简介 Git是一个开源的分布式版本控制系统&#xff0c;它可以实现有效控制应用版本&#xff0c;但是在一旦在代码发布的时候&#xff0c;存在不规范的操作及配置&#xff0c;就很可能将源代码泄露出去。那么&#xff0c;一旦攻击者发现这个问题之后&#xff0c;就…

论文速览 | IEEE Symposium on Security and Privacy (SP), 2023 | FMCW雷达反射阵列欺骗攻击

注1:本文系"计算成像最新论文速览"系列之一,致力于简洁清晰地介绍、解读非视距成像领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, SIGGRAPH, TPAMI; Light‑Science & Applications, Optica 等)。 本次介绍的论文是:<I…

MariaDB 修改用户密码的 SQL

有时候我们希望能够修改数据库中访问用户的密码。 但是我们只能 SQL 登录服务器后才能进行修改。 修改的 SQL 为&#xff1a; ALTER USER root% IDENTIFIED WITH mysql_native_password BY 123;针对实际上数据的配置情况&#xff0c;上面的 SQL 是需要进行一些调整的。 MySQ…

鸿蒙云函数调试坑点

如果你要本地调试请使用 const {payload, action} event.body/** 本地调试不需要序列化远程需要序列化 */ // const {payload, action} JSON.parse(event.body) const {payload, action} event.body 注意: 只要修改云函数&#xff0c;必须上传云函数 如果使用 const {pay…

25计算机考研院校数据分析 | 南京大学

南京大学&#xff08;Nanjing University&#xff09;&#xff0c;简称“南大”&#xff0c;是中华人民共和国教育部直属、中央直管副部级建制的全国重点大学&#xff0c;国家首批“双一流”、“211工程”、“985工程”重点建设高校&#xff0c;入选首批“珠峰计划”、“111计划…

WordPress AI Engine 插件 文件上传致RCE漏洞复现(CVE-2023-51409)

0x01 产品简介 AI Engine插件是WordPress中的AI一体化解决方案,包括创建聊天机器人、生成内容和图像、推荐标题和帖子摘录、支持多种人工智能引擎等功能,可以节省用户时间。 0x02 漏洞概述 WordPress AI Engine 插件upload接口存在文件上传漏洞,未经身份验证的远程攻击者…

(四)Servlet教程——Maven的安装与配置

1.在C盘根目录下新建一个Java文件夹,该文件夹用来放置以下步骤下载的Maven&#xff1b; 2. 下载Maven的来源有清华大学开源软件镜像站和Apache Maven的官网&#xff0c;由于清华大学开源软件镜像站上只能下载3.8.8版本以上的Maven&#xff0c;我们选择在Apache Maven的官网上下…

codeforce#933 题解

E. Rudolf and k Bridges 题意不讲了&#xff0c;不如去题干看图。 传统dp&#xff0c;每个点有两个选择&#xff0c;那么建桥要么不建。需要注意的是在状态转移的时候&#xff0c;桥是有长度的&#xff0c;如果不建需要前d格中建桥花费最少的位置作为状态转移的初态。 #incl…