• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用HiTraceMeter跟踪性能(C/C++)
2
3## 简介
4
5HiTraceMeter提供系统性能打点接口。开发者通过在关键代码位置调用HiTraceMeter接口提供的API接口,能够有效跟踪进程轨迹、查看系统性能。
6
7## 基本概念
8
9**HiTraceMeter Tag**:跟踪数据使用类别,称作HiTraceMeter Tag,一般每个软件子系统对应一个tag。[hitrace](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/dfx/hitrace.md)命令行工具采集跟踪数据时,只采集给定的tag类别选项指定的跟踪数据。应用中的HiTraceMeter打点的tag是HITRACE_TAG_APP,对应[hitrace](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/dfx/hitrace.md)命令`hitrace -l`列出的tag列表中的app。
10
11## 实现原理
12
131. 应用程序通过HiTraceMeter函数接口进行打点,HiTraceMeter函数将跟踪数据通过内核sysfs文件接口输入到内核的ftrace数据缓冲区。
142. [hitrace](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/dfx/hitrace.md)命令行工具读取内核ftrace缓冲区中的跟踪数据,将跟踪数据输出到设备侧的文件中。
15
16## 接口说明
17
18性能打点跟踪接口由HiTraceMeter模块提供,详细API请参考[性能打点跟踪API参考](../reference/apis-performance-analysis-kit/_hitrace.md)。
19
20| 方法                                                         | 接口描述                   |
21| ------------------------------------------------------------ | -------------------------- |
22| void OH_HiTrace_StartTrace(const char* name)                 | 开启一个同步时间片跟踪事件 |
23| void OH_HiTrace_FinishTrace()                                | 结束一个同步时间片跟踪事件 |
24| void OH_HiTrace_StartAsyncTrace(const char* name, int32_t taskId) | 开启一个异步时间片跟踪事件 |
25| void OH_HiTrace_FinishAsyncTrace(const char* name, int32_t taskId) | 结束一个异步时间片跟踪事件 |
26| void OH_HiTrace_CountTrace(const char* name, int64_t count)  | 整数跟踪事件               |
27
28> **注意:**
29>
30> 用户态tarce格式使用竖线 `|` 作为分隔符,所以通过HiTraceMeter接口传递的字符串类型参数应避免包含该字符,防止trace解析异常。
31
32HiTraceMeter打点接口按功能/行为分类,主要分三类:同步时间片跟踪接口、异步时间片跟踪接口和整数跟踪接口。无论同步时间片跟踪接口还是异步时间片跟踪接口,接口本身都是同步接口,不是异步接口。HiTraceMeter打点接口可与[HiTraceChain](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/dfx/hitracechain-guidelines-arkts.md)一起使用,进行跨设备/跨进程/跨线程打点与分析。
33
34- 同步时间片跟踪接口用于顺序执行的打点场景。
35- 异步时间片跟踪接口用于在异步操作执行前进行开始打点,在异步操作完成后进行结束打点。异步跟踪的开始和结束由于不是顺序发生的,解析trace时需要通过name与taskId参数进行识别,name与taskId参数相同的异步跟踪开始与结束打点相匹配。
36- 整数跟踪接口用于跟踪整数变量。
37
38**参数解析**
39
40| 参数名 | 类型   | 必填 | 说明                                                         |
41| ------ | ------ | ---- | ------------------------------------------------------------ |
42| name   | string | 是   | 要跟踪的数值变量名称。                                       |
43| taskId | number | 是   | 用来表示关联的ID,如果有多个name相同的任务是并行执行的,则每次调用startTrace的taskId不同。 |
44| count  | number | 是   | 变量的值。                                                   |
45
46## 开发示例
47
48在DevEco Studio中创建Native C++工程,使用HiTraceMeter NDK_C打点接口,以下为一个Native C++工程示例。
49
501. 新建一个Native C++工程,工程目录结构如下:
51
52   ```text
53   ├── entry
54   │   ├── src
55   │       ├── main
56   │       │   ├── cpp
57   │       │   │   ├── CMakeLists.txt
58   │       │   │   ├── napi_init.cpp
59   │       │   │   └── types
60   │       │   │       └── libentry
61   │       │   │           ├── Index.d.ts
62   │       │   │           └── oh-package.json5
63   │       │   ├── ets
64   │       │   │   ├── entryability
65   │       │   │   │   └── EntryAbility.ets
66   │       │   │   ├── entrybackupability
67   │       │   │   │   └── EntryBackupAbility.ets
68   │       │   │   └── pages
69   │       │   │       └── Index.ets
70   ```
71
722. 在"CMakeLists.txt"文件末尾新增如下内容,添加libhitrace_ndk.z.solibhilog_ndk.z.so动态链接库。
73
74   ```cmake
75   target_link_libraries(entry PUBLIC libhitrace_ndk.z.so libhilog_ndk.z.so)
76   ```
77
783. 编辑"napi_init.cpp"文件,在Add函数中调用HiTraceMeter NDK_C的接口,进行性能打点跟踪, 示例代码如下:
79
80   ```c++
81   #include "hilog/log.h"
82   #include "hitrace/trace.h"
83   #include "napi/native_api.h"
84
85   #undef LOG_TAG
86   #define LOG_TAG "traceTest"
87
88   static napi_value Add(napi_env env, napi_callback_info info)
89   {
90       // 第一个异步跟踪任务开始
91       OH_HiTrace_StartAsyncTrace("myTestAsyncTrace", 1001);
92       // 开始计数任务
93       int64_t traceCount = 0;
94       traceCount++;
95       OH_HiTrace_CountTrace("myTestCountTrace", traceCount);
96       // 业务流程
97       OH_LOG_INFO(LogType::LOG_APP, "myTraceTest running, taskId: 1001");
98
99       // 第二个异步跟踪任务开始,同时第一个跟踪的同名任务还没结束,出现了并行执行,对应接口的taskId需要不同
100       OH_HiTrace_StartAsyncTrace("myTestAsyncTrace", 1002);
101       // 开始计数任务
102       traceCount++;
103       OH_HiTrace_CountTrace("myTestCountTrace", traceCount);
104       // 业务流程
105       OH_LOG_INFO(LogType::LOG_APP, "myTraceTest running, taskId: 1002");
106
107       // 结束taskId为1001的异步跟踪任务
108       OH_HiTrace_FinishAsyncTrace("myTestAsyncTrace", 1001);
109       // 结束taskId为1002的异步跟踪任务
110       OH_HiTrace_FinishAsyncTrace("myTestAsyncTrace", 1002);
111
112       // 开始同步跟踪任务
113       OH_HiTrace_StartTrace("myTestSyncTrace");
114       // 业务流程
115       OH_LOG_INFO(LogType::LOG_APP, "myTraceTest running, synchronizing trace");
116       // 结束同步跟踪任务
117       OH_HiTrace_FinishTrace();
118
119       size_t requireArgc = 2;
120       size_t argc = 2;
121       napi_value args[2] = {nullptr};
122
123       napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);
124
125       napi_valuetype valuetype0;
126       napi_typeof(env, args[0], &valuetype0);
127
128       napi_valuetype valuetype1;
129       napi_typeof(env, args[1], &valuetype1);
130
131       double value0;
132       napi_get_value_double(env, args[0], &value0);
133
134       double value1;
135       napi_get_value_double(env, args[1], &value1);
136
137       napi_value sum;
138       napi_create_double(env, value0 + value1, &sum);
139
140       return sum;
141   }
142
143   EXTERN_C_START
144   static napi_value Init(napi_env env, napi_value exports)
145   {
146       napi_property_descriptor desc[] = {
147           { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
148       };
149       napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
150       return exports;
151   }
152   EXTERN_C_END
153
154   static napi_module demoModule = {
155       .nm_version = 1,
156       .nm_flags = 0,
157       .nm_filename = nullptr,
158       .nm_register_func = Init,
159       .nm_modname = "entry",
160       .nm_priv = ((void*)0),
161       .reserved = { 0 },
162   };
163
164   extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
165   {
166       napi_module_register(&demoModule);
167   }
168   ```
169
1704. 在DevEco Studio Terminal窗口中执行如下命令,开启应用trace捕获:
171
172   ```shell
173   PS D:\xxx\xxx> hdc shell
174   $ hitrace --trace_begin app
175   ```
176
1775. 单击DevEco Studio界面上的运行按钮,启动应用,点击屏幕中间的字符串,执行包含HiTraceMeter打点的业务逻辑,然后执行如下命令抓取trace数据:
178
179   ```shell
180   $ hitrace --trace_dump | grep myTest
181   ```
182
183   成功抓取的trace数据如下所示:
184
185   ```text
186   <...>-21458   (-------) [009] .... 372404.331037: tracing_mark_write: S|21458|H:myTestAsyncTrace|1001
187   <...>-21458   (-------) [009] .... 372404.331040: tracing_mark_write: C|21458|H:myTestCountTrace|1
188   <...>-21458   (-------) [009] .... 372404.331083: tracing_mark_write: S|21458|H:myTestAsyncTrace|1002
189   <...>-21458   (-------) [009] .... 372404.331085: tracing_mark_write: C|21458|H:myTestCountTrace|2
190   <...>-21458   (-------) [009] .... 372404.331091: tracing_mark_write: F|21458|H:myTestAsyncTrace|1001
191   <...>-21458   (-------) [009] .... 372404.331093: tracing_mark_write: F|21458|H:myTestAsyncTrace|1002
192   <...>-21458   (-------) [009] .... 372404.331095: tracing_mark_write: B|21458|H:myTestSyncTrace
193   ```
194
1956. 执行如下命令,结束应用trace捕获:
196
197   ```shell
198   $ hitrace --trace_finish
199   ```
200