class="hide-preCode-box">

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
@Component
export struct IconItem {
image: string | Resource = '';
text: string | Resource = '';
build() {
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center, alignContent: FlexAlign.Center }) {
Image(this.image)
.height(40)
.width(40)
.objectFit(ImageFit.Contain)
.margin({
left: 15
})
Text(this.text)
.fontSize(20)
.fontColor(Color.Black)
.width(100)
.height(50)
.textAlign(TextAlign.Center)
}
.width('100%')
.height(50)
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
下面使用SmartPerf-Host调试工具抓取htrace文件,并生成一个跟踪泳道分析图,来了解示例代码的加载流程。跟踪泳道分析图被分为五个部分,每个部分都标注数字并框选出相应的标签,从而使得整体的过程能够得到更好的理解。
图6 LazyForEach遍历的列表的泳道分析图

接下来,逐一解析这五个模块的详情:
1.加载并路由LazyForEach页面
图7 加载并路由LazyForEach页面泳道图

H:JsiDeclarativeEngine::LoadPageSource加载一个 JavaScript 文件,并且解析为 ABC 字节码;H:FlushPipelineWithoutAnimation 清理渲染管道的操作;H:CustomNode:OnAppear 用于构建当前 OnAppear 生命周期的操作,并执行aboutToAppear生命周期函数;H:CustomNode:BuildItem LazyForEachPage 渲染子节点并挂载在 LazyForEachPage 页面上。
2.对当前帧节点Stage,执行布局任务、执行渲染任务并通知图形侧进行渲染
图8 对当前帧节点Stage,执行布局任务、执行渲染任务并通知图形侧进行渲染泳道图

H:Layout[stage][self:1][parent:0]对当前帧节点Stage,执行布局任务;(Stage作为框架,承载着页面Page节点。因此,标签的呈现会从Stage开始)
H:Measure[%s][self:17][parent:16] 对Page、Column、Row、Image、Text等组件布局尺寸计算;H:Builder:BuildLazyItem [0]和H:ListLayoutAlgorithm::MeasureListItem:0 分别为创建一个LazyItem项目和计算列表项的布局尺寸;H:Layout[%s][self:38][parent:37] 对Page、Column、Row、Image、Text等组件执行布局任务;
H:FrameNode::RenderTask 执行渲染任务;H:RequestNextVSync 请求下一帧Vsync信号。
3.对当前帧节点Flex,执行布局任务、执行渲染任务并通知图形侧进行渲染
图9 对当前帧节点Flex,执行布局任务、执行渲染任务并通知图形侧进行渲染泳道图

H:Layout[Flex][self:63][parent:62]对当前帧节点Flex,执行布局任务**;**
H:Measure[%s][self:17][parent:16] 对Image、Text等组件布局尺寸计算;
H:FrameNode::RenderTask Flex渲染任务执行;H:RequestNextVSync 请求下一帧Vsync信号。
4.构建前预处理数据及添加预测布局任务
图10 构建前预处理数据及添加预测布局任务泳道图

H:Builder:BuildLazyItem [11]构建前预处理数据了11条数据;H:Layout[ListItem][self:76][parent:-1] 添加一条Flex、Image、Text的预测布局;H:FlushMessages 发送消息通知图形侧进行渲染。
5.合成渲染树上各节点图层任务
图11 合成渲染树上各节点图层任务泳道图

H:AcquireBuffer、H:ProcessSurfaceNode:EntryView XYWH[0 0 720 1280]获取屏幕缓冲区并绘制EntryView、SystemUi_StatusBar、SystemUi_NavigationBar等;H:Repaint 硬件合成器合成绘制当前节点树。
自定义Trace
开发者可以根据业务需求,使用hiTraceMeter进行自定义Trace打点跟踪,目前支持ArkTS和Native,具体使用细节可参考下方链接:
性能打点跟踪开发指导(ArkTS)
性能打点跟踪开发指导(Native)
添加自定义Trace后,可在SmartPerf-Host调试工具上查看,自定义Trace将以独立泳道的形式呈现在对应打点的进程下。
下图两条泳道使用了startTrace和finishTrace方法,表示程序运行过程中,指定标签从调用startTrace到调用finishTrace的耗时统计。图中记录了CUSTOM_TRACE_TAG_1和CUSTOM_TRACE_TAG_2两个标签,先后呈现了2个标签的耗时统计。
图12 自定义Trace示例

下图两条泳道使用了TraceByValue方法,表示程序运行过程中,指定Trace在对应时间段内的状态值,状态值含义可按需传参,开发者可以通过鼠标放置在对应数据块上,来查看具体的状态值。图中记录了CUSTOM_TRACE_TAG_2标签在红色方框标识的时间段内,打点状态值为2001。
图13 自定义状态值示例

性能打点原理
Trace的生成依赖了DFX子系统中的HiTrace组件,其中包含的hiTraceMeter模块为开发者提供系统性能打点接口,具体细节可参考下方链接:
HiTrace组件
hiTraceMeter模块
hiTraceMeter拥有两套开始和结束打点接口,实现对逻辑行为的耗时统计。由于耗时统计大多数以方法为单位,所以hiTraceMeter也提供了快速打点单个方法执行耗时的宏定义HITRACE_METER、HITRACE_METER_NAME、HITRACE_METER_FMT,使用它们,只需要在方法起始位置调用即可。这些宏定义依赖了方法内局部变量的生命周期,其原理是在方法开始时构造了一个打点实例,在实例构造函数中调用开始打点接口,当方法执行完毕,打点实例随着方法结束而执行析构,在实例析构函数中调用结束打点接口。
App中的打点示例
ArkUI框架子系统应用hiTraceMeter的例子,来源于ArkUI开发框架源码。
以下代码对hiTraceMeter进行接口封装,其原理与HITRACE_METER等相同,依赖方法内局部变量的生命周期实现快速打点。
#define ACE_SCOPED_TRACE(fmt, ...) AceScopedTrace aceScopedTrace(fmt, ##__VA_ARGS__)
#define ACE_FUNCTION_TRACE() ACE_SCOPED_TRACE(__func__)
class ACE_FORCE_EXPORT AceScopedTrace final {
public:
explicit AceScopedTrace(const char* format, ...) __attribute__((__format__(printf, 2, 3)));
~AceScopedTrace();
ACE_DISALLOW_COPY_AND_MOVE(AceScopedTrace);
private:
bool traceEnabled_ { false };
};
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
以下代码是刷新视图同步事件,包括记录帧信息、刷新任务、绘制渲染上下文、处理用户输入。在方法开头调用宏定义ACE_FUNCTION_TRACE,将函数名FlushVsync作为Trace名称记录下来,并记录函数开始时间,在函数结束时记录函数结束时间,得出执行耗时。
void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount)
{
ACE_FUNCTION_TRACE();
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
RS中的打点示例
图形子系统应用hiTraceMeter的例子,来源于图形子系统源码。
以下代码对hiTraceMeter进行接口封装。
#include "hitrace_meter.h"
#define ROSEN_TRACE_BEGIN(tag, name) StartTrace(tag, name)
#define RS_TRACE_BEGIN(name) ROSEN_TRACE_BEGIN(HITRACE_TAG_GRAPHIC_AGP, name)
#define ROSEN_TRACE_END(tag) FinishTrace(tag)
#define RS_TRACE_END() ROSEN_TRACE_END(HITRACE_TAG_GRAPHIC_AGP)
#define RS_TRACE_NAME(name) HITRACE_METER_NAME(HITRACE_TAG_GRAPHIC_AGP, name)
#define RS_TRACE_NAME_FMT(fmt, ...) HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, fmt, ##__VA_ARGS__)
#define RS_ASYNC_TRACE_BEGIN(name, value) StartAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, name, value)
#define RS_ASYNC_TRACE_END(name, value) FinishAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, name, value)
#define RS_TRACE_INT(name, value) CountTrace(HITRACE_TAG_GRAPHIC_AGP, name, value)
#define RS_TRACE_FUNC() RS_TRACE_NAME(__func__)
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
以下代码在显示器画面绘制方法。在方法开头调用宏定义RS_TRACE_NAME,将函数名ProcessDisplayRenderNode与对应的显示器id组合后,作为Trace名称记录下来,同时由于其本质是使用了快速打点单个方法的宏定义HITRACE_METER_NAME,于是只需要调用一次,即可收集到ProcessDisplayRenderNode函数的执行起终点时间,得出执行耗时。
void RSSurfaceCaptureVisitor::ProcessDisplayRenderNode(RSDisplayRenderNode &node)
{
RS_TRACE_NAME("RSSurfaceCaptureVisitor::ProcessDisplayRenderNode:" +
std::to_string(node.GetId()));
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
《鸿蒙开发学习手册》:
- 基本概念
- 构建第一个ArkTS应用
- ……

- 应用基础知识
- 配置文件
- 应用数据管理
- 应用安全管理
- 应用隐私保护
- 三方应用调用管控机制
- 资源分类与访问
- 学习ArkTS语言
- ……

- Ability开发
- UI开发
- 公共事件与通知
- 窗口管理
- 媒体
- 安全
- 网络与链接
- 电话服务
- 数据管理
- 后台任务(Background Task)管理
- 设备管理
- 设备使用信息统计
- DFX
- 国际化开发
- 折叠屏系列
- ……


1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/138232397","extend1":"pc","ab":"new"}">>
id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension">
class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}">
class="blog_extension_card_left">
class="blog_extension_card_cont">
鸿蒙开发学习资料领取!!!
class="blog_extension_card_cont_r">
微信名片
评论记录:
回复评论: