OpenHarmony实战开发-

简介

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.hqwc.cn/news/643357.html

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

相关文章

Maven基础篇7

私服-idea访问私服与组件上传 公司团队开发流程 本地上传–>repository–>私服 其他成员从私服拿 1.项目完成后发布到私服 在pom文件最后写上发布的配置管理 ​ //写发布的url也就是你发布到哪一个版本&#xff0c;以及写入id ​ ​ 发布的时候&#xff0c;将项…

STM32F103ZET6+TFTLCD实现亮屏——1

工程思路 利用1个GPIO控制背光&#xff0c;在利用FSMC去控制TFTCLCD的控制引脚和数据引脚 FSMC是什么 STM32中的FSMC&#xff08;Flexible Static Memory Controller&#xff0c;灵活静态存储器控制器&#xff09;是一个硬件模块&#xff0c;它允许微控制器与外部存储器接口&…

实验七 智能手机互联网程序设计(微信程序方向)实验报告

请编写一个用户登录界面&#xff0c;提示输入账号和密码进行登录&#xff0c;要求在输入后登陆框显示为绿色&#xff1b; 二、实验步骤与结果&#xff08;给出对应的代码或运行结果截图&#xff09; index.wxml <view class"content"> <view class"a…

Docker容器:镜像与容器命令管理

目录 一、镜像管理命令 1、搜索镜像 2、获取镜像 3、镜像加速下载 4、查看下载的镜像文件信息 5、查看下载到本地的所有镜像 6、获取指定镜像的详细信息 7、为本地的镜像添加新的标签 8、删除镜像 8.1 删除指定的镜像 8.2 批量删除多个镜像 9、导出镜像与导入镜像 …

25计算机考研院校数据分析 | 上海交通大学

上海交通大学电子信息与电气工程学院成立于2001年12月&#xff0c;其前身可湖源至百年前的电机专科&#xff0c;具有中国电气工程师“摇篮”之美称。50年代根据学科发展需要分为电工与计算机科学系(三系)和电子工程系(四系)。1985年&#xff0c;三系和四系合并&#xff0c;成立…

(C语言入门)数组

目录 什么是数组&#xff1f; 数组&#xff1a; 数组的使用&#xff1a; 数组的初始化&#xff1a; 数组名&#xff1a; 数组案例&#xff1a; 一维数组的最大值&#xff1a; 一维数组的逆置&#xff1a; 数组和指针&#xff1a; 通过指针操作数组元素&#xff1a; …

Kibana安装部署(Linux)

Kibana是Elasticsearch的开源可视化工具&#xff0c;与存储在Elasticsearch中的数据进行交互。 1. 下载软件 这里使用的Elasticsearch的版本是7.12.0&#xff0c;所以kibana选择同样的7.12.0版本。 官网下载地址&#xff1a;https://www.elastic.co/cn/downloads/past-releas…

爱上JDK源码阅读-枚举类

在日常开发中&#xff0c;经常会用到枚举类。这篇文章主要探讨一下枚举类和普通类有什么区别&#xff0c;以及编译过程中偷偷做了什么事情。 知识点 枚举类的本质编译器对枚举类的改动 先看一段简单的枚举类代码&#xff1a; enum StatusType {ON(1) ,OFF(2);StatusType(int …

手机号码携号转网查询API接口是什么

手机号码携号转网查询API接口又叫运营商携号转网查询API接口&#xff0c;是指通过手机号精准查询该号码转网前及转网后所归属运营商。运营商携号转网查询API接口多用于营销场景&#xff0c;如运营商业务办理、客户信息查询、携号转网、电话营销等&#xff0c;接下来我们聊一聊怎…

什么是Spring Security?具有哪些功能?

本篇将带你快速了解什么是Spring Security&#xff0c;通过入门案例以及相关原理和类的分析让你快速入门。 一、概述 官网&#xff1a;https://spring.io/projects/spring-security Spring Security是一个Java框架&#xff0c;用于保护应用程序的安全性。它提供了一套全面的安全…

好看的混淆矩阵

网上绘制的混淆矩阵都不太满意。。。经过本人多次实验&#xff0c;如下混淆矩阵最为美观&#xff0c;特此记录 import matplotlib matplotlib.use(Agg) from matplotlib import rcParamsimport matplotlib.pyplot as plt import numpy as np# 给定混淆矩阵 cm np.array([[683…

5000字干货:如何通过社区驱动增长?挑战、认知、本质和六个步骤!

本来不少平台建立社区是为了给用户提供归属感,但在商业压力下,不得不开始做增长的运营。但不是说只是简单地“做增长”就可以的,归属感和增长,两者看起来相似,但生产流程却完全不同。这种情况下,我们需要怎么做? 2024年经济压力下,CEO向各社区负责人下达了一个目标:实…