1# HiTraceMeter开发指导 2 3## HiTraceMeter概述 4 5### 简介 6 7HiTraceMeter在OpenHarmony中,为开发者提供业务流程调用链跟踪的维测接口。通过使用该接口所提供的功能,可以帮助开发者迅速获取指定业务流程调用链的运行日志、定位跨设备/跨进程/跨线程的故障问题。HiTraceMeter用来支持用户态的打点,采集用户态和内核态的trace数据,从而进行性能跟踪与分析的系统。 8 9### 基本概念 10 11HiTraceMeter系统主要分为三部分: 12 13- JS/C++应用打点API; 14- Trace数据采集命令行工具; 15- Trace数据图形分析工具。 16 17其中,前两者运行在设备端侧,图形工具运行在PC主机侧。打点API部分提供了C++和JS接口,供开发过程中打点使用,打点用于产生Trace数据流,是抓Trace数据的基础条件。 18 19命令行工具用于采集Trace数据,用来抓取Trace数据流并保存到文本文件。 20 21Trace数据分析可以在图形工具中人工分析,也可以使用分析脚本自动化分析,Trace分析工具以Trace命令行工具的采集结果数据文件为输入。 22 23 HiTraceMeter跟踪数据使用类别分类,类别分类称作Trace Tag或Trace Category,一般一个端侧软件子系统对应一个Tag。该Tag在打点API中以类别Tag参数传入。Trace命令行工具采集跟踪数据时,只采集Tag类别选项指定的跟踪数据。应用程序跟踪数据标签都是属于APP Tag,从而JS接口不需要输入tag参数。目前HiTraceMeter支持的Trace Tag表如下(可在hitrace_meter.h [hitrace_meter.h](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h) 中查看): 24 25```cpp 26constexpr uint64_t HITRACE_TAG_NEVER = 0; // This tag is never enabled. 27constexpr uint64_t HITRACE_TAG_ALWAYS = (1ULL << 0); // This tag is always enabled. 28constexpr uint64_t HITRACE_TAG_DLP_CREDENTIAL = (1ULL << 21); // This tag is dlp credential service. 29constexpr uint64_t HITRACE_TAG_ACCESS_CONTROL = (1ULL << 22); // This tag is access control tag. 30constexpr uint64_t HITRACE_TAG_NET = (1ULL << 23); // Net tag. 31constexpr uint64_t HITRACE_TAG_NWEB = (1ULL << 24); // NWeb tag. 32constexpr uint64_t HITRACE_TAG_HUKS = (1ULL << 25); // This tag is huks. 33constexpr uint64_t HITRACE_TAG_USERIAM = (1ULL << 26); // This tag is useriam. 34constexpr uint64_t HITRACE_TAG_DISTRIBUTED_AUDIO = (1ULL << 27); // Distributed audio tag. 35constexpr uint64_t HITRACE_TAG_DLSM = (1ULL << 28); // device security level tag. 36constexpr uint64_t HITRACE_TAG_FILEMANAGEMENT = (1ULL << 29); // filemanagement tag. 37constexpr uint64_t HITRACE_TAG_OHOS = (1ULL << 30); // OHOS generic tag. 38constexpr uint64_t HITRACE_TAG_ABILITY_MANAGER = (1ULL << 31); // Ability Manager tag. 39constexpr uint64_t HITRACE_TAG_ZCAMERA = (1ULL << 32); // Camera module tag. 40constexpr uint64_t HITRACE_TAG_ZMEDIA = (1ULL << 33); // Media module tag. 41constexpr uint64_t HITRACE_TAG_ZIMAGE = (1ULL << 34); // Image module tag. 42constexpr uint64_t HITRACE_TAG_ZAUDIO = (1ULL << 35); // Audio module tag. 43constexpr uint64_t HITRACE_TAG_DISTRIBUTEDDATA = (1ULL << 36); // Distributeddata manager module tag. 44constexpr uint64_t HITRACE_TAG_MDFS = (1ULL << 37); // Mobile distributed file system tag. 45constexpr uint64_t HITRACE_TAG_GRAPHIC_AGP = (1ULL << 38); // Graphic module tag. 46constexpr uint64_t HITRACE_TAG_ACE = (1ULL << 39); // ACE development framework tag. 47constexpr uint64_t HITRACE_TAG_NOTIFICATION = (1ULL << 40); // Notification module tag. 48constexpr uint64_t HITRACE_TAG_MISC = (1ULL << 41); // Notification module tag. 49constexpr uint64_t HITRACE_TAG_MULTIMODALINPUT = (1ULL << 42); // Multi modal module tag. 50constexpr uint64_t HITRACE_TAG_SENSORS = (1ULL << 43); // Sensors mudule tag. 51constexpr uint64_t HITRACE_TAG_MSDP = (1ULL << 44); // Multimodal Sensor Data Platform module tag. 52constexpr uint64_t HITRACE_TAG_DSOFTBUS = (1ULL << 45); // Distributed Softbus tag. 53constexpr uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag. 54constexpr uint64_t HITRACE_TAG_ARK = (1ULL << 47); // ARK tag. 55constexpr uint64_t HITRACE_TAG_WINDOW_MANAGER = (1ULL << 48); // window manager tag. 56constexpr uint64_t HITRACE_TAG_ACCOUNT_MANAGER = (1ULL << 49); // account manager tag. 57constexpr uint64_t HITRACE_TAG_DISTRIBUTED_SCREEN = (1ULL << 50); // Distributed screen tag. 58constexpr uint64_t HITRACE_TAG_DISTRIBUTED_CAMERA = (1ULL << 51); // Distributed camera tag. 59constexpr uint64_t HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK = (1ULL << 52); // Distributed hardware fwk tag. 60constexpr uint64_t HITRACE_TAG_GLOBAL_RESMGR = (1ULL << 53); // Global resource manager tag. 61constexpr uint64_t HITRACE_TAG_DEVICE_MANAGER = (1ULL << 54); // Distributed hardware devicemanager tag. 62constexpr uint64_t HITRACE_TAG_SAMGR = (1ULL << 55); // SA tag. 63constexpr uint64_t HITRACE_TAG_POWER = (1ULL << 56); // power manager tag. 64constexpr uint64_t HITRACE_TAG_DISTRIBUTED_SCHEDULE = (1ULL << 57); // Distributed schedule tag. 65constexpr uint64_t HITRACE_TAG_DEVICE_PROFILE = (1ULL << 58); // device profile tag. 66constexpr uint64_t HITRACE_TAG_DISTRIBUTED_INPUT = (1ULL << 59); // Distributed input tag. 67constexpr uint64_t HITRACE_TAG_BLUETOOTH = (1ULL << 60); // bluetooth tag. 68constexpr uint64_t HITRACE_TAG_ACCESSIBILITY_MANAGER = (1ULL << 61); // accessibility manager tag. 69constexpr uint64_t HITRACE_TAG_APP = (1ULL << 62); // App tag. 70 71constexpr uint64_t HITRACE_TAG_LAST = HITRACE_TAG_APP; 72constexpr uint64_t HITRACE_TAG_NOT_READY = (1ULL << 63); // Reserved for initialization. 73constexpr uint64_t HITRACE_TAG_VALID_MASK = ((HITRACE_TAG_LAST - 1) | HITRACE_TAG_LAST); 74``` 75 76### 实现原理 77 78HiTraceMeter主要提供抓取用户态和内核态Trace数据的命令行工具,提供用户态打点的innerkits接口(c++)和kits接口(js),HiTraceMeter基于内核ftrace提供的用户态打点的扩展,利用ftrace的trace_marker节点,将用户空间通过打点接口写入的数据写进内核循环buffer缓冲区。其基本架构图如下: 79 80 81 82 83 84 85 86### 约束与限制 87 88- HiTraceMeter所有功能与接口的实现都依赖于内核提供的ftrace功能,ftrace 是内核提供的一个 framework,采用 plugin 的方式支持开发人员添加更多种类的 trace 功能,因此使用HiTraceMeter之前要使能 ftrace,否则HiTraceMeter的功能无法使用(目前大部分Linux内核默认使能了ftrace,关于ftrace的详细介绍可查看内核ftrace相关资料 89 [ftrace相关资料](https://blog.csdn.net/Luckiers/article/details/124646205) )。 90- HiTraceMeter仅限小型系统、标准系统下使用。 91 92 93 94## HiTraceMeter开发指导 95 96HiTraceMeter分为JS/C++应用打点API与数据采集命令行工具hitrace,下面分别介绍接口和命令行工具。 97 98 99 100### 场景介绍 101 102在实际开发过程中,开发者可能会遇到app卡顿或者在代码调试过程中需要查看代码调用流程,HiTraceMeter接口提供了相应的接口来跟踪程序延时和代码调用流程,分析性能问题。 103 104### 接口说明 105 106C++接口仅系统开发者使用,JS(目前暂未开放js接口)应用开发者可以略过本节。标准系统上接口描述如下(hitrace_meter.h [hitrace_meter.h](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/interfaces/native/innerkits/include/hitrace_meter/hitrace_meter.h) ): 107 108**表 1** 同步接口 109 110| Sync trace | 功能描述 | 参数说明 | 111|:---------------------------------------------------------------------------- | --------- | --------------------------------------------------------------------- | 112| void StartTrace(uint64_t label, const std::string& value, float limit = -1); | 启动同步trace | label: Trace category。<br />value: Trace携带的信息,表明当前的某种状态,例如内存大小,队列长短等。 | 113| void FinishTrace(uint64_t label); | 关闭同步trace | label: Trace category。 | 114 115同步接口StartTrace和FinishTrace必须配对使用,FinishTrace和前面最近的StartTrace进行匹配。StartTrace和FinishTrace函数对可以嵌套模式使用,跟踪数据解析时使用栈式数据结构进行匹配。接口中的limit参数用于限流,使用默认值即可。 116 117**表 2** 异步接口 118 119| Async trace | 功能描述 | 参数说明 | 120| ------------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------- | 121| void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit = -1); | 开启异步trace | label: Trace category。<br />value: Trace携带的信息,表明当前的某种状态,例如内存大小,队列长短等。<br />taskId:异步Trace中用来表示关联的ID。 | 122| void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId); | 关闭异步trace | label: Trace category。<br />value: Trace携带的信息,表明当前的某种状态,例如内存大小,队列长短等。<br />taskId:异步Trace中用来表示关联的ID。 | 123 124 125 126异步接口StartAsyncTrace和FinishAsyncTrace的跟踪数据匹配时,使用参数中的value和taskId配对匹配,可以不按顺序使用,主要用于异步场景。在C++程序中,使用异步跟踪的场景很少。 127 128**表 3** 计数器接口 129 130| Counter Trace | 功能描述 | 参数说明 | 131| ------------------------------------------------------------------ | ------- | -------------------------------------------------------------- | 132| void CountTrace(uint64_t label, const std::string& name, int64_t); | 计数trace | label: Trace category。<br />name: Trace的名称,IDE中会以此字段展示这段Trace。 | 133 134### 开发步骤 135 1361. 编译依赖添加,需要修改的编译配置文件base\hiviewdfx\hitrace\cmd\BUILD.gn 。 137 138 ``` 139 external_deps = [ "hitrace:hitrace_meter"] 140 ``` 141 1422. 头文件依赖添加。 143 144 ```cpp 145 #include "hitrace_meter.h"//接口函数定义头文件 146 ``` 147 1483. 接口调用,将需要跟踪的Trace value传入参数,目前HiTraceMeter支持的Trace Tag在基本概念hitrace_meter.h中都已列出,我们以OHOS这个Tag为例,假设我们需要获取func1,func2函数的Trace数据,参考下面实例,在shell中执行hitrace命令后会自动抓取Trace数据,抓到的Trace数据中包括了函数调用过程以及调用过程消耗的内存和时间,可用于分析代码调用流程,代码性能问题。 149 150 ```cpp 151 #include "hitrace_meter.h" // 包含hitrace_meter.h 152 using namespace std; 153 154 int main() 155 { 156 uint64_t label = BYTRACE_TAG_OHOS; 157 sleep(1); 158 CountTrace(label, "count number", 2000); // 整数跟踪 159 160 StartTrace(label, "func1Trace", -1); // func1Start的跟踪起始点 161 sleep(1); 162 StartTrace(label, "func2Trace", -1); // func2Start的跟踪起始点 163 sleep(2); 164 FinishTrace(label); // func2Trace的结束点 165 sleep(1); 166 FinishTrace(label); // func1Trace的结束点 167 168 StartAsyncTrace(label, "asyncTrace1", 1234); // 异步asyncTrace1的开始点 169 FinishAsyncTrace(label, "asyncTrace1", 1234); // 异步asyncTrace1的结束点 170 171 return 0; 172 } 173 ``` 174 1754. 使用方法,打点编译部署完成后,运行下面命令行来抓取Trace。然后在端侧shell里运行应用,可以抓取到Trace数据。 176 177 ``` 178 hdc_std shell hitrace -t 10 ohos > .\myapp_demo.ftrace 179 ``` 180 181 抓取之后的数据可以在smartperf中"Open trace file"或者直接拖入图形区打开,关于smartperf的详细介绍可查看 [smartperf](https://toscode.gitee.com/openharmony-sig/smartperf) 。 182 183### 调测验证 184 185以下为一个demo调试过程,该demo使用了同步接口中的StartTrace和FinishTrace。 186 1871. 编写测试代码hitrace_example.cpp( [hitrace_example.cpp](https://gitee.com/openharmony/hiviewdfx_hitrace/blob/master/example/hitrace_example.cpp) ),将使用到的接口加入代码: 188 189 ```cpp 190 int main() 191 { 192 thread t1(ThreadFunc1); 193 t1.join(); 194 195 StartTrace(LABEL, "testStart"); 196 sleep(SLEEP_ONE_SECOND); 197 198 StartTrace(LABEL, "funcAStart", SLEEP_ONE_SECOND); // 打印起始点 199 FuncA(); 200 FinishTrace(LABEL); 201 sleep(SLEEP_TWO_SECOND); 202 203 thread t2(ThreadFunc2); 204 t2.join(); 205 206 StartTrace(LABEL, "funcBStart", SLEEP_TWO_SECOND); 207 FuncB(); 208 FinishTrace(LABEL);// 打印结束点 209 sleep(SLEEP_TWO_SECOND); 210 211 sleep(SLEEP_ONE_SECOND); 212 FinishTrace(LABEL); 213 FuncC(); 214 215 return 0; 216 } 217 ``` 218 2192. 修改gn编译文件并编译,编译配置文件路径base\hiviewdfx\hitrace\cmd\BUILD.gn 。 220 221 ``` 222 ohos_executable("hitrace_example") { 223 sources = [ "example/hitrace_example.cpp" ] 224 225 external_deps = [ "hitrace:hitrace_meter" ] 226 227 subsystem_name = "hiviewdfx" 228 part_name = "hitrace_native" 229 } 230 231 group("hitrace_target") { 232 deps = [ 233 ":hitrace", 234 ":hitrace_example", 235 ] 236 } 237 ``` 238 2393. 将编译出来的hitrace_example可执行文件放到设备中的/system/bin目录下,在shell中执行依次执行如下命令: 240 241 ```shell 242 hitrace --trace_begin ohos 243 hitrace_exampe 244 hitrace --trace_dump 245 ``` 246 247 当我们看到Trace数据中有我们需要的Trace value时,说明成功抓取Trace,成功的数据如下所示: 248 249 ``` 250 <...>-1651 (-------) [002] .... 327.194136: tracing_mark_write: S|1650|H:testAsync 111 251 <...>-1650 (-------) [001] .... 332.197640: tracing_mark_write: B|1650|H:testStart 252 <...>-1650 (-------) [001] .... 333.198018: tracing_mark_write: B|1650|H:funcAStart 253 <...>-1650 (-------) [001] .... 334.198507: tracing_mark_write: E|1650| 254 <...>-1654 (-------) [003] .... 341.201673: tracing_mark_write: F|1650|H:testAsync 111 255 <...>-1650 (-------) [001] .... 341.202168: tracing_mark_write: B|1650|H:funcBStart 256 <...>-1650 (-------) [001] .... 343.202557: tracing_mark_write: E|1650| 257 <...>-1650 (-------) [001] .... 346.203178: tracing_mark_write: E|1650| 258 <...>-1650 (-------) [001] .... 346.203457: tracing_mark_write: C|1650|H:count number 1 259 <...>-1650 (-------) [001] .... 347.203818: tracing_mark_write: C|1650|H:count number 2 260 <...>-1650 (-------) [001] .... 348.204207: tracing_mark_write: C|1650|H:count number 3 261 <...>-1650 (-------) [001] .... 349.204473: tracing_mark_write: C|1650|H:count number 4 262 <...>-1650 (-------) [001] .... 350.204851: tracing_mark_write: C|1650|H:count number 5 263 <...>-1655 (-------) [001] .... 365.944658: tracing_mark_write: trace_event_clock_sync: realtime_ts=1502021460925 264 <...>-1655 (-------) [001] .... 365.944686: tracing_mark_write: trace_event_clock_sync: parent_ts=365.944641 265 ``` 266 267 268 269## HiTraceMeter命令行工具使用指导 270 271HiTraceMeter提供了可执行的二进制程序hitrace,设备刷openharmony后直接在shell中运行以下命令,抓取内核运行的数据,当前支持的操作如下: 272 273**表 4** 命令行列表 274 275| Option | Description | 276| ----------------------------- | -------------------------------------------------------- | 277| -h,--help | 查看option帮助 | 278| -b n,--buffer_size n | 指定n(KB)内存大小用于存取trace日志,默认2048KB | 279| -t n,--time n | 用来指定trace运行的时间(单位:s),取决于需要分析过程的时间 | 280| --trace_clock clock | trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot | 281| --trace_begin | 启动抓trace | 282| --trace_dump | 将数据输出到指定位置(默认控制台) | 283| --trace_finish | 停止抓trace,并将数据输出到指定位置(默认控制台) | 284| --trace_finish_nodump | 停止抓trace,不输出trace信息 | 285| -l,--list_categories | 输出手机能支持的trace模块 | 286| --overwrite | 当缓冲区满的时候,将丢弃最新的信息(默认丢弃最老的日志) | 287| -o filename,--output filename | 指定输出的目标文件名称 | 288| -z | 抓取trace后进行压缩 | 289 290以下是常用hitrace命令示例,供开发者参考: 291 292- 查询支持的label。 293 294 ``` 295 296 hitrace -l 297 298 ``` 299 300 或者 301 302 ``` 303 304 hitrace --list_categories 305 306 ``` 307 308- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 309 310 ``` 311 312 hitrace -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace 313 314 ``` 315 316- 设置trace的输出时钟为mono。 317 318 ``` 319 320 hitrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace 321 322 ``` 323 324- 抓取trace后进行压缩。 325 326 ``` 327 328 hitrace -z -b 4096 -t 10 --overwrite ability > /data/log/mytrace.ftrace 329 330 ``` 331 332 333 334## 常见问题 335 336#### hitrace抓数据不全或者没抓到数据 337 338##### 现象描述 339 340执行hitrace命令抓数据不全或者没抓到数据。 341 342##### 根因分析 343 344参数-t 时间设置过小或者-b缓冲区buffer设置过小导致数据丢失。 345 346##### 解决方法 347 348可设置-t 60,-b 204800扩大抓trace时间和缓冲区buffer解决。 349 350 351 352## 参考 353 354更多关于HiTraceMeter的详细内容请参考:[轻量级的分布式调用链跟踪](https://gitee.com/openharmony/hiviewdfx_hitrace) 。 355