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

news2025/1/16 10:54:50

简介

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.coloradmin.cn/o/1628484.html

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

相关文章

C#技巧之窗体去鼠标化

简介 在窗体程序中不用鼠标&#xff0c;直接使用键盘完成想要的操作。 实现的方法有两种&#xff0c;一种是使用键盘上的Tab键使控件获得焦点&#xff0c;然后用enter键触发该控件上的事件&#xff08;一般为click事件&#xff09;。另一种是&#xff0c;为控件添加快捷键&am…

优维全新力作:统一采控平台

在本月&#xff0c;优维新一代核心系统「EasyOps」7.0大版本重磅上线&#xff0c;为广大用户带来了“更核心、更智能、更开放、更客制”的产品能力。&#xff08;点击回看&#xff1a;重磅&#xff01;优维科技发布EasyOps7.0大版本&#xff09;在本次版本能力分享上&#xff0…

基于springboot实现中药实验管理系统设计项目【项目源码+论文说明】计算机毕业设计

基于springboot实现中药实验管理系统设计演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了中药实验管理系统的开发全过程。通过分析中药实验管理系统管理的不足&#xff0c;创建了一个计算机管理中药实验管…

基于WOA鲸鱼优化的购售电收益与风险评估算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于WOA鲸鱼优化的购售电收益与风险评估算法.WOA优化算法是一种基于鲸鱼捕食过程的仿生优化算法&#xff0c;其包括鲸鱼行走觅食、鲸鱼包围以及鲸鱼螺旋捕食三个步骤。在WOA优…

用 Python 创建 Voronoi 图

概述 最常见的空间问题之一是找到距离我们当前位置最近的兴趣点 (POI)。假设有人很快就会耗尽汽油&#xff0c;他/她需要在为时已晚之前找到最近的加油站&#xff0c;解决这个问题的最佳解决方案是什么&#xff1f;当然&#xff0c;驾驶员可以检查地图来找到最近的加油站&…

C++从入门到精通——string类

string类 前言一、为什么学习string类C语言中的字符串示例 二、标准库中的string类string类string类的常用接口说明string类对象的常见构造string类对象的容量操作string的接口测试及使用string类对象的访问及遍历操作下标和方括号遍历范围for遍历迭代器遍历相同的代码&#xf…

6.模板初阶

目录 1.泛型编程 2. 函数模板 2.1 函数模板概念 2.2函数模板格式 2.3 模板的实现 2.4函数模板的原理 2.5 函数模板的实例化 3.类模板 1.泛型编程 我们如何实现一个 交换函数呢&#xff1f; 使用函数重载虽然可以实现&#xff0c;但是有一下几个不好的地方&#xff1a; …

iOS - 多线程-读写安全

文章目录 iOS - 多线程-读写安全1. 多读单写1.1 场景1.2 实现方案1.2.1 pthread_rwlock&#xff1a;读写锁1.2.1.1 示例 1.2.2 dispatch_barrier_async&#xff1a;异步栅栏调用1.2.2.1 示例 iOS - 多线程-读写安全 假设有一个文件&#xff0c;A线程进行读取操作&#xff0c;B…

刷题日记 ---- 顺序表与链表相关经典算法题(C语言版)

目录 1. 移除元素2. 合并两个有序数组3. 移除链表元素4. 反转链表5. 合并两个有序链表6. 链表的中间结点7. 环形链表的约瑟夫问题8. 分割链表总结 正文开始 1. 移除元素 题目链接: 移除元素 题目描述: 思路历程: 题目明确要求, 不能使用额外的数组空间, 也就是说不可以创建…

linux系统-FTP服务配置

目录 一、FTP简介 1.什么是FTP&#xff1f;&#xff1f;&#xff1f; 2.FTP的两种模式 二、安装配置FTP服务 1.关闭防火墙和核心防护 2.安装VSFTPD 3.修改配置文件 4.黑白名单设置 一、FTP简介 1.什么是FTP&#xff1f;&…

【Node.js工程师养成计划】之打造自己的脚手架工具

一、创建全局的自定义命令 1、打开一个空文件夹&#xff0c;新建一个bin文件夹&#xff0c;在bin文件夹下新建cli.js文件&#xff0c;js文件可以命名为cli.js&#xff08;您随意&#xff09; 2、在cli.js文件中的开头&#xff08;&#xff01;&#xff01;&#xff09;写下面这…

Prometheus Metrics指标类型 Gauge(仪表盘)

指标是用来衡量性能、消耗、效率和许多其他软件属性随时间的变化趋势。它们允许工程师通过警报和仪表盘来监控一系列测量值的演变&#xff08;如CPU或内存或磁盘使用量、请求持续时间、延迟等&#xff09;。指标在IT监控领域有着悠久的历史&#xff0c;并被工程师广泛使用&…

Linux下的UDEV机制/守护进程

一. Udev机制 二. 守护进程 1. 概念&#xff1a; 2. 基本特点&#xff1a; a. 生存周期长&#xff0c;一般操作系统启动的时候就启动&#xff0c;关闭的时候关闭&#xff08;这是由开发人员自行将守护进程添加到开机启动项的&#xff09;。 b. 守护进程和终端无关联&#…

云备份项目->配置环境

升级gcc到7.3版本 sudo yum install centos-release-scl-rh centos-release-scl sudo yum install devtoolset-7-gcc devtoolset-7-gcc-c source /opt/rh/devtoolset-7/enable echo "source /opt/rh/devtoolset-7/enable" >> ~/.bashrc 安装Jsoncpp库 sud…

知识分享之cookie

http协议中的cookie&#xff0c;什么是cookie如何获取cookie 一、什么是Cookie Cookie&#xff08;曲奇&#xff0c;小甜饼的译名&#xff09;在互联网技术领域中&#xff0c;是指一种小型文本文件&#xff0c;它由网站服务器发送给用户的浏览器&#xff0c;并被浏览器存储在用…

【春 联---turtle海龟画图】

春联 又称"春贴"、"门对"、"对联"&#xff0c;是过年时所贴的红色喜庆元素"年红"中一个种类。它以对仗工整、简洁箱巧的文字描绘美好形象&#xff0c;抒发美好愿 望&#xff0c;是中国特有的文学形式&#xff0c;是华人们过年 的重要习…

windows/linux 安装php的 sql server 扩展

Windowsphpstudyphp7.1 下载&#xff1a;ODBC、下载php 的sql server 扩展 路径&#xff1a;下载地址 版本&#xff1a;我的是7.1 对应的ODBC 是13&#xff0c;php 的sql server 扩展为4.3 安装&#xff1a;msodbcsql 直接安装、sqlsrv43 安装完把 扩展复制到php71 的扩展文…

c#学习入门2

十、运算符 1&#xff09;算术运算符是用于数值类型变量计算的运算符&#xff0c;它返回的结果是数值 1.赋值符号 2.算数运算符 加 减- 乘* 除/ 取余% 3.算数运算符的优先级 4.算术运算符的复合运算 5.算术运算符的自增减 2&#xff09;字符串拼接 1.字符串拼接方式1 注意&…

antd 日期控件RangePicker如何增加快捷键(日/周/月/年)

注意&#xff1a;快捷键是从当前日期往前推算的 效果 代码 <script><RangePickerranges{{日: [moment(new Date().setDate(new Date().getDate() - 1)), moment(new Date())],周: [moment(new Date().setDate(new Date().getDate() - 7)), moment(new Date())],月: […

淘宝API接口教程:淘宝商品详情API接口(标题|主图|SKU|价格|商品销量..)

淘宝商品详情数据接口是用于获取商品详细信息的API&#xff0c;它允许开发者检索商品的各类数据。 要使用淘宝商品详情数据接口&#xff0c;你需要遵循以下步骤&#xff1a; 注册账号和权限申请&#xff1a;在淘宝开放平台注册开发者账号&#xff0c;并申请所需API的权限。完…