鸿蒙系列-如何使用DevEco分析app的性能

news2025/2/24 7:27:00

如何使用DevEco分析app的性能

性能优化、启动优化、内存优化、FPS监测、性能分析🧐

在鸿蒙OpenHarmony开发过程中,开发者开发的代码(Stage 模型)通常以调用 ArkUI 框架的代码为主,主要优化的代码部分也在其中,那么如何验证自己的代码是否起到了优化效果,就需要工具对比分析优化前和优化后的效果。
我们以一次测试过程为例,介绍如何分析性能。

构造场景,验证 RelativeContainer() 提升性能的能力

测试方法:我们使用对比测试的方法,比较使用 RelativeContainer() 前后可以对比的性能指标,来证明合理使用布局是对性能提升有帮助的。

测试工具:DevEco 中的 Profiler 工具。
图标以此对应可以监测的场景有:启动、帧率、耗时、内存。

测试的关键点如下:

  1. 将 Text 作为最小单元,Row 作为模拟嵌套层级使用的容器,RelativeContainer() 作为相对布局使用的容器。
  2. 将定义一组(10)颜色循环使用,这个颜色用做 Text 的背景色,用于直观地区分每个 Text 组件。(定义10个是为了代码更易读,也方便以10为单位扩展,生成20、30、40等数据📊)
  3. 使用 50 个 Text 组件连续嵌套,测试嵌套层级为 50 级的情况。Row() 是我们用于嵌套的容器。代码放在 Stack50View.ets
  4. 将 50 个 Text 组件平铺成 1 层,测试嵌套层级为 2 级( 50个Text层 + RelativeContainer()层)的情况。 RelativeContainer() 是我们用于减少布局嵌套层数的容器。代码放在 Relative50View.ets
  5. 对比第3点和第4点的渲染时间和内存情况,试图以此来证明使用 RelativeContainer() 布局可以优化性能。

定义的颜色如下:

const COLORS = [Color.Blue, Color.Green, Color.Pink, Color.Brown, Color.Grey,
Color.White, Color.Black, Color.Orange, Color.Yellow, Color.Red]

通过编码使得 Relative50View.ets 和 Stack50View.ets 能产生一样的视觉效果,在每个 Text 上编号以区分,效果如下:

然后,把他们放在一个list里,一共10行,效果如下:

测试结果:

启动分析,启动后6s内的性能分析

不使用 RelativeContainer() 的情况:

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  build() {
    Column() {
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
      Stack50View()
    }
  }
}

在这里插入图片描述

使用 RelativeContainer() 的情况:

在这里插入图片描述

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  build() {
    Column() {
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
      Relative50View()
    }
  }
}

内存分析,启动后6s内的内存分析

不使用 RelativeContainer() 的情况:

在这里插入图片描述

使用 RelativeContainer() 的情况:

在这里插入图片描述

帧率分析,上下滑动 list 时候的帧率变化

定义100个item放到list中

不使用 RelativeContainer() 的情况:

@Entry
@Component
struct Index {
  @State arr: number[] = Array.from(Array(100).keys()); 

  build() {
    Column() {
      List() {
        ForEach(this.arr,
          (item) => {
            ListItem() {
              Stack50View()
            }
          },
          (item) => item.toString()
        )
      }
    }
  }
}

在这里插入图片描述

使用 RelativeContainer() 的情况:

在这里插入图片描述

@Entry
@Component
struct Index {
  @State arr: number[] = Array.from(Array(100).keys());

  build() {
    Column() {
      List() {
        ForEach(this.arr,
          (item) => {
            ListItem() {
              // Stack50View()
              Relative50View()
            }
          },
          (item) => item.toString()
        )
      }
    }
  }
}

结论:

这么看对比效果不佳。

对比项启动分析(onCreate)内存分析滑动时卡顿率(jank rate)
优化前1.374ms-8.2%
优化后1.697ms-13.4%

进一步测试

验证嵌套层级深度对性能有影响。
对比如下数据:

  1. 构建 50 层嵌套,只在第50层加一个text
  2. 构建 1 层嵌套,加一个text
对比项启动分析(onCreate)内存分析滑动时卡顿率(jank rate)
优化前0.821ms-0.5%
优化后0.027ms-0.0%

在这里插入图片描述

在这里插入图片描述

通过多组数据可以画出折线图:

结论:组件嵌套会增加渲染时间和内存。

对比测试

通过 Frame 监测列表下 render_service(1132) 中的 VSync-app 1374 中框选时间片段得到:

对比项1层嵌套10层嵌套20层嵌套30层嵌套40层嵌套50层嵌套
time---757.1ms512.4ms757.1ms
occurrences---684768
FPS---909089

结论:从嵌套50层仍有89帧来看,说明嵌套对帧率变化影响不明显。

其他代码如下:

Relative50View.ets


const COLORS = [Color.Blue, Color.Green, Color.Pink, Color.Brown, Color.Grey,
Color.White, Color.Black, Color.Orange, Color.Yellow, Color.Red]

@Builder function TextBuilder(index: number) {
  Text(`${index%10}`)
    .fontColor(Color.White)
    .fontSize(9)
    .alignRules({
      top: { anchor: '__container__', align: VerticalAlign.Top },
      left: { anchor: '__container__', align: HorizontalAlign.Start }
    })
    .id(`figure${index}`)
    .backgroundColor(COLORS[index%10])
    .align(Alignment.TopStart)
    .height(70)
    .margin({ top: 0, left: 5 * index })
}

@Preview
@Component
export struct Relative50View {
  build() {
    Row() {
      Row() {
        RelativeContainerBuilder1()
      }
      .width('100%')
    }
    .height(100)
  }
}

@Builder function RelativeContainerBuilder1() {
  RelativeContainer() {
    TextBuilder(0)
    TextBuilder(1)
    TextBuilder(2)
    TextBuilder(3)
    TextBuilder(4)
    TextBuilder(5)
    TextBuilder(6)
    TextBuilder(7)
    TextBuilder(8)
    TextBuilder(9)
    // 10
    TextBuilder(10)
    TextBuilder(11)
    TextBuilder(12)
    TextBuilder(13)
    TextBuilder(14)
    TextBuilder(15)
    TextBuilder(16)
    TextBuilder(17)
    TextBuilder(18)
    TextBuilder(19)
    // 20
    TextBuilder(20)
    TextBuilder(21)
    TextBuilder(22)
    TextBuilder(23)
    TextBuilder(24)
    TextBuilder(25)
    TextBuilder(26)
    TextBuilder(27)
    TextBuilder(28)
    TextBuilder(29)
    // 30
    TextBuilder(30)
    TextBuilder(31)
    TextBuilder(32)
    TextBuilder(33)
    TextBuilder(34)
    TextBuilder(35)
    TextBuilder(36)
    TextBuilder(37)
    TextBuilder(38)
    TextBuilder(39)
    // 40
    TextBuilder(40)
    TextBuilder(41)
    TextBuilder(42)
    TextBuilder(43)
    TextBuilder(44)
    TextBuilder(45)
    TextBuilder(46)
    TextBuilder(47)
    TextBuilder(48)
    TextBuilder(49)
  }
}

Stack50View.ets

const COLORS = [Color.Blue, Color.Green, Color.Pink, Color.Brown, Color.Grey,
Color.White, Color.Black, Color.Orange, Color.Yellow, Color.Red]

@Preview
@Component
export struct Stack50View {
  build() {
    Row() {
      Row() {
        StackBuilder1()
      }
      .width('100%')
    }
    .height(100)
  }
}

@Builder function TextBuilder(index: number, group: number) {
  Text(`${index%10}`)
    .fontColor(Color.White)
    .fontSize(9)
    .backgroundColor(COLORS[index%10])
    .align(Alignment.TopStart)
    .height(70)
}

// 构建 1 层嵌套,加一个text
@Builder function StackBuilder3() {
  Row() {
    Text(`${50}`)
      .fontColor(Color.White)
      .fontSize(9)
      .backgroundColor(COLORS[0])
      .align(Alignment.TopStart)
      .height(50)
  }
}

// 构建 50 层嵌套,只在第50层加一个text
@Builder function StackBuilder2(index: number) {
  Row() {
    if (index > 0) {
      StackBuilder2(index-1)
    } else {
      Text(`${50}`)
        .fontColor(Color.White)
        .fontSize(9)
        .backgroundColor(COLORS[index%10])
        .align(Alignment.TopStart)
        .height(50)
    }
  }
}

// 构建 50 层嵌套,每一层增加一个text
@Builder function StackBuilder1() {
  Row() {
    TextBuilder(0, 0)
    Row() {
      TextBuilder(1, 0)
      Row() {
        TextBuilder(2, 0)
        Row() {
          TextBuilder(3, 0)
          Row() {
            TextBuilder(4, 0)
            Row() {
              TextBuilder(5, 0)
              Row() {
                TextBuilder(6, 0)
                Row() {
                  TextBuilder(7, 0)
                  Row() {
                    TextBuilder(8, 0)
                    Row() {
                      TextBuilder(9, 0)
                      // 10
                      Row() {
                        TextBuilder(10, 1)
                        Row() {
                          TextBuilder(11, 1)
                          Row() {
                            TextBuilder(12, 1)
                            Row() {
                              TextBuilder(13, 1)
                              Row() {
                                TextBuilder(14, 1)
                                Row() {
                                  TextBuilder(15, 1)
                                  Row() {
                                    TextBuilder(16, 1)
                                    Row() {
                                      TextBuilder(17, 1)
                                      Row() {
                                        TextBuilder(18, 1)
                                        Row() {
                                          TextBuilder(19, 1)
                                          //20
                                          Row() {
                                            TextBuilder(20, 2)
                                            Row() {
                                              TextBuilder(21, 2)
                                              Row() {
                                                TextBuilder(22, 2)
                                                Row() {
                                                  TextBuilder(23, 2)
                                                  Row() {
                                                    TextBuilder(24, 2)
                                                    Row() {
                                                      TextBuilder(25, 2)
                                                      Row() {
                                                        TextBuilder(26, 2)
                                                        Row() {
                                                          TextBuilder(27, 2)
                                                          Row() {
                                                            TextBuilder(28, 2)
                                                            Row() {
                                                              TextBuilder(29, 2)
                                                              // 30
                                                              Row() {
                                                                TextBuilder(30, 3)
                                                                Row() {
                                                                  TextBuilder(31, 3)
                                                                  Row() {
                                                                    TextBuilder(32, 3)
                                                                    Row() {
                                                                      TextBuilder(33, 3)
                                                                      Row() {
                                                                        TextBuilder(34, 3)
                                                                        Row() {
                                                                          TextBuilder(35, 3)
                                                                          Row() {
                                                                            TextBuilder(36, 3)
                                                                            Row() {
                                                                              TextBuilder(37, 3)
                                                                              Row() {
                                                                                TextBuilder(38, 3)
                                                                                Row() {
                                                                                  TextBuilder(39, 3)
                                                                                  // 40
                                                                                  Row() {
                                                                                    TextBuilder(40, 4)
                                                                                    Row() {
                                                                                      TextBuilder(41, 4)
                                                                                      Row() {
                                                                                        TextBuilder(42, 4)
                                                                                        Row() {
                                                                                          TextBuilder(43, 4)
                                                                                          Row() {
                                                                                            TextBuilder(44, 4)
                                                                                            Row() {
                                                                                              TextBuilder(45, 4)
                                                                                              Row() {
                                                                                                TextBuilder(46, 4)
                                                                                                Row() {
                                                                                                  TextBuilder(47, 4)
                                                                                                  Row() {
                                                                                                    TextBuilder(48, 4)
                                                                                                    Row() {
                                                                                                      TextBuilder(49, 4)


                                                                                                    }
                                                                                                  }
                                                                                                }
                                                                                              }
                                                                                            }
                                                                                          }
                                                                                        }
                                                                                      }
                                                                                    }
                                                                                  }
                                                                                }
                                                                              }
                                                                            }
                                                                          }
                                                                        }
                                                                      }
                                                                    }
                                                                  }
                                                                }
                                                              }
                                                            }
                                                          }
                                                        }
                                                      }
                                                    }
                                                  }
                                                }
                                              }
                                            }
                                          }
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

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

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

相关文章

Java“牵手”易贝商品列表数据,关键词搜索易贝商品数据接口,易贝API申请指南

ebay商城是一个网上购物平台,售卖各类商品,包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取ebay商品列表和商品详情页面数据,您可以通过开放平台的接口或者直接访问ebay商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

2023年9月CSPM-3国标项目管理中级认证报名,来弘博创新

CSPM-3中级项目管理专业人员评价,是中国标准化协会(全国项目管理标准化技术委员会秘书处),面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系,建立健全人才职业能力评价和激励机制的要…

喜报 | 人大金仓荣获2023“金鼎奖”,金融系统解决方案再获认可

近日,由中国人民银行旗下《金融电子化》杂志社评选的2023“金鼎奖”结果正式揭晓。人大金仓“基于金仓关系型数据库供应链金融系统解决方案”,获得了来自中国人民银行以及银行、保险、证券、基金等各类型金融机构专家的一致认可,荣获“优秀网…

Redis的基本操作与应用(附相关面试题...)

一、数据类型与操作步骤 1、概述:Redis是一款基于内存以KV键值对存储的中间件技术,常用做缓存,支持数据持久化。 2、数据类型: 常用5种数据类型:String(字符串)、List(列表)、set(集合)、ha…

GaussDB数据库SQL系列-数据去重

目录 一、前言 二、数据去重应用场景 三、数据去重案例(GaussDB) 1、示例场景描述 2、定义重复数据 3、制定去重规则 4、创建测试数据(GaussDB) 5、编写去重方法(GaussDB) 6、附:全字段…

【Linux安装java环境】超简单,以jdk8为例

文章目录 前言详细步骤总结 前言 一些小伙伴在到手一台虚拟机后,发现需要配置java环境,看了文章后会发现超级简单,以下内容以安装jdk1.8为例。 详细步骤 查看是否存在java环境java -version若弹出找不到java命令,执行下一步。官…

【2023高教社杯】C题 蔬菜类商品的自动定价与补货决策 问题分析、数学模型及python代码实现

【2023高教社杯】C题 蔬菜类商品的自动定价与补货决策 1 题目 C题蔬菜类商品的自动定价与补货决策 在生鲜商超中,一般蔬菜类商品的保鲜期都比较短,且品相随销售时间的增加而变差, 大部分品种如当日未售出,隔日就无法再售。因此&…

BLE架构与开源协议栈

BLE架构: 简单来说,BLE协议栈可以分成三个部分,主机(host)程序,控制器(controller)程序,主机控制器接口(HCI)。如果再加上底层射频硬件和顶层用户程序,则构成了完整的BLE协议,如下图所示&#…

@Autowired为什么会报错?如何解决?

作者 | 磊哥 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) Autowired报错信息相信大部分程序员都遇到过,奇怪的是虽然代码报错,但丝毫不影响程序的正常执行&…

第一次去新加坡Token2049?这份行前攻略请收好

TOKEN2049是行业领先的Web3盛会,往届的Token2049,知名项目的创始人主会场遍地跑,了解亚洲区块链前沿,BD更多新项目,寻找潜在投资机会,Token2049不会让你失望。 Moonbeam中文社区今年也会出席Token2049系列活…

安科瑞智能微型断路器在某银行网点的设计与应用

安科瑞 崔丽洁 【摘要】:随着人工智能、移动互联等现代信息技术和通信技术在电力行业的应用,实现电力系统各个环节人机交互、万物互联,打造状态全方面感知、信息合理处理、应用便捷灵活的泛在电力物联网已成为必然趋势。本文主要对智能微型断…

C++ 围炉札记

文章目录 内存检测ProtoBufCMake、vscode、clion、Qt右值1、临时变量右值引用2、右值引用本质 函数返回std::functionPOD(Plain Old Data)thread_localnew / delete1、定位new运算符 可变参数模板typename和class1、C模板类头文件和实现文件分离的方法2、…

BT8959T2/5 LCD 驱动

1 Preface/Foreword LCD驱动路径:app/gui/lcd/ SDK默认的LCD驱动:lcd_gc9c01.c 2 数据结构 3 代码分析

高忆管理:科创板中签率?

科创板于当时已经成为出资者追捧的板块,许多新股都在科创板上市,那么科创板新股的中签率是高仍是低呢?是取决于哪些要素形成的呢?下面,本文将从多个角度剖析这个问题。 一、科创板中签率是什么? ​ 科创…

LeetCode 1126.查询活跃业务

数据准备 Create table If Not Exists Events (business_id int, event_type varchar(10), occurences int); Truncate table Events; insert into Events (business_id, event_type, occurences) values (1, reviews, 7); insert into Events (business_id, event_type, occu…

三段视频怎么合并在一起?三种方法教你快速合并

合并视频可以节省存储空间。如果我们有多个视频文件,每个文件可能需要一定的存储空间。但是,如果将它们合并到一个文件中,就可以节省存储空间并更轻松地管理文件。此外合并视频还使其更易于共享。如果需要将视频发送给其他人,您只…

Python实操:内存管理与优化策略

在 Python 开发过程中,合理有效地管理和优化内存使用是提高程序性能和效率的关键。本文将深入探讨 Python 中的内存管理机制,并分享一些实用的优化策略和具体操作步骤,帮助您更好地利用资源、减少内存占用并提升代码执行速度。 一、了解 Pyth…

【Python】【Fintech】解决用pandas_datareader从yahoo下载股票数据时出错

【背景】 要做一个预测投资组合portfolio未来收益的python脚本,类似的功能需要从数据源获取相关指数和股票的数据,一直以来都是用pandas_datareader从yahoo上面拿,但是后来忽然发现不能用了,这篇就说明一下遇到此问题的walk around. 【分析】 由于数据源是yahoo那边的,…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十二:通用详情组件封装实现

一、本章内容 本章实现通用详情组件,自动识别实体配置信息,并自动生成对应组件,填充组件数据,并完成数据自动加载等过程。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址࿱

Vue 前端项目使用alibaba矢量库svg图标

Vue 前端项目使用alibaba矢量库svg图标 这里主要是记录 vue项目中使用阿里矢量库图标的操作流程,方便以后查阅!!! 一、简介 iconfont 是由阿里巴巴体验团队打造的,一款设计和前端开发的便捷工具.拥有着很强大且图标内…