• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# hiprofiler
2
3<!--Kit: Performance Analysis Kit-->
4<!--Subsystem: HiviewDFX-->
5<!--Owner: @zyxzyx-->
6<!--Designer: @Maplestroy-->
7<!--Tester: @gcw_KuLfPSbe-->
8<!--Adviser: @foryourself-->
9
10
11## Hiprofiler简介
12
13
14HiProfiler调优组件旨在为开发者提供一系列调优能力,可以用来帮助分析内存、性能等问题。
15
16
17整体架构包括PC端和设备端。主体部分是PC端的数据展示页面和设备端的性能调优服务。PC端和设备端服务采用C/S模型,PC端的调优数据在[DevEco Studio](https://cbg.huawei.com/#/group/ipd/DevEcoToolsList)和[Smartperf](https://gitee.com/openharmony/developtools_smartperf_host)网页中展示。设备端程序运行在系统环境中,包含多个部分,其中hiprofilerd进程负责与DevEco通信,作为调优服务。设备端还包括命令行工具hiprofiler_cmd和数据采集进程hiprofiler_plugins。调优服务控制数据采集进程获取调优数据,数据最终流向DevEco Studio,整个过程可抽象为生产者-消费者模型。目前已完成多个插件,包括nativehook、CPU、ftrace、GPU、hiperf、xpower和memory数据采集,实现了CPU、GPU、内存和能耗等多维度调优。
18
19
20
21Hiprofiler工具对标业界调优工具,并提供更多能力,比如[跨语言回栈、能耗数据获取、长时间堆内存抓栈功能](#插件参数说明)等。
22
23
24
25## 环境要求
26
27- 根据hdc命令行工具指导,完成[环境准备](hdc.md#环境准备)。
28
29- 确保设备已正常连接,并执行hdc shell。
30
31
32## 架构简介
33
341. PC端通过DevEco或Smartperf调用hiprofiler_cmd命令行工具;
35
362. hiprofiler_cmd进程启动hiprofilerd调优服务和hiprofiler_plugins插件进程;
37
383. hiprofiler_plugins开启对应插件,将获取到的调优数据汇总至hiprofilerd进程;
39
404. hiprofilerd进程将调优数据以proto格式存储到文件,或者实时返回给PC端;
41
425. PC端解析数据,生成泳道,展示获取到的调优数据。
43
44![zh-cn_image_0000002381835609](figures/zh-cn_image_0000002381835609.png)
45
46
47## 命令行说明
48
49使用hiprofiler_cmd命令行工具可以调用不同插件并输入不同参数,以满足不同的调优需求。示范命令如下:
50
51```shell
52$ hiprofiler_cmd \
53  -c - \
54  -o /data/local/tmp/hiprofiler_data.htrace \
55  -t 30 \
56  -s \
57  -k \
58<<CONFIG
59 request_id: 1
60 session_config {
61  buffers {
62   pages: 16384
63  }
64 }
65 plugin_configs {
66  plugin_name: "ftrace-plugin"
67  sample_interval: 1000
68  config_data {
69   hitrace_categories: "binder"
70   buffer_size_kb: 204800
71   flush_interval_ms: 1000
72   flush_threshold_kb: 4096
73   trace_period_ms: 200
74  }
75 }
76CONFIG
77```
78
79
80| 命令 | 命令说明 |
81| -------- | -------- |
82| -c | 设置该选项后,需要将配置文件放入/data/local/tmp目录下,将路径作为参数输入。 |
83| -o | 自定义文件保存路径(需要以/data/local/tmp开头)。若不设置路径,则调优数据自动保存至/data/local/tmp/hiprofiler_data.htrace。重复调优会覆盖原来路径的文件。 |
84| -k | 杀掉已存在的调优服务进程。 |
85| -s | 拉起调优服务进程。 |
86| -t | 设置调优持续时间,单位:s。 |
87
88
89输入完hiprofiler_cmd参数后,需要输入插件配置信息,以&lt;&lt;CONFIG开头,CONFIG结尾,中间内容以json格式输入。
90
91
92以下是session config字段介绍:
93
94
95| 字段 | 字段说明 |
96| -------- | -------- |
97| buffers | 共享内存页的数量。 |
98| split_file | 是否拆分文件。true代表拆分文件;false代表不拆分文件。 |
99| split_file_max_size_mb | 设置split_file为true的情况下,定义每个拆分文件的最大大小。 |
100
101
102plugin_configs字段介绍:
103
104
105| 字段 | 字段说明 |
106| -------- | -------- |
107| plugin_name | 开启插件的名字。 |
108| sample_interval | 插件获取调优数据的间隔,单位:ms。 |
109| config_data | 插件具体参数。每个插件需要的参数不同,参考各插件proto定义。<br/>(代码路径:developtools/profiler/protos)。 |
110
111
112生成的trace文件通过hdc file recv命令导到本地,然后上传到smartperf网站或者DevEco Studio进行解析。
113
114
115## 支持插件列表
116
117| 插件名字 | 简介 | 规格说明 |
118| -------- | -------- | -------- |
119| native_hook | 获取堆内存分配的调用栈信息。 | 采集的进程仅支持[使用调试证书签名的应用](#使用调试证书签名的应用) |
120| ftrace-plugin | 获取内核打点的trace事件,以及hitrace打点的数据。 | - |
121| cpu-plugin | 获取进程CPU使用率信息,包括进程级和线程级的使用率。 | - |
122| gpu-plugin | 获取进程GPU使用率信息。 | - |
123| xpower-plugin | 获取进程能耗使用情况的数据。 | - |
124| memory-plugin | 获取进程内存占用情况,主要是获取进程smaps节点的数据。 | - |
125| diskio plugin | 获取进程磁盘空间占用情况。 | - |
126| network profiler | 通过进程内打点,获取进程HTTP请求的详细信息。 | 采集的进程仅支持[使用调试证书签名的应用](#使用调试证书签名的应用) |
127| network plugin | 获取进程网络流量统计信息。 | - |
128| hisysevent plugin | 通过hisysevent命令,获取hisysevent的事件记录数据。 | - |
129| hiperf plugin | 通过调用hiperf命令获取进程的指令计数信息以及对应的堆栈。 | - |
130| hidump plugin | 通过SP_daemon命令获取相关数据。 | - |
131
132
133## 使用调试证书签名的应用
134
135
136> **注意:**
137>
138> 确认命令指定的应用是否为可调试应用,可执行hdc shell "bm dump -n bundlename | grep appProvisionType"查询,预期返回信息为"appProvisionType": "debug"。
139
140以包名com.example.myapplication为例,可执行如下命令查询:
141
142```shell
143hdc shell "bm dump -n com.example.myapplication | grep appProvisionType"
144```
145
146如果包名对应的应用是可调试应用,预期返回信息如下:
147
148```shell
149"appProvisionType": "debug",
150```
151
152构建可调试应用需要使用调试证书进行签名,申请调试证书及签名可参考:[申请调试证书](https://developer.huawei.com/consumer/cn/doc/app/agc-help-add-debugcert-0000001914263178)153
154
155## 插件参数说明
156
157**native_hook 插件**
158
159获取堆内存分配的调用栈信息(通过malloc、mmap、calloc或realloc等基础库函数分配堆内存的调用栈),包括跨语言堆内存分配信息(如在ArkTS语言中调用napi分配native堆内存),还能展示内存泄漏未释放堆内存调用栈信息。
160
161nativehook参数列表:
162
163| 参数名字 | 类型 | 参数含义 | 详细介绍 |
164| -------- | -------- | -------- | -------- |
165| fp_unwind | bool | true表示使用fp回栈方式进行回栈;<br/>false表示使用dwarf回栈方式进行回栈。 | fp回栈是利用了x29寄存器保存的fp指针,函数的fp指针始终指向父函数(调用方)的fp指针,调优服务根据这一特点进行回栈,根据ip计算相对PC,然后查找maps对应区间来进行符号化。<br/>由于现在编译期越来越优化,出现寄存器重用或者编译禁用fp,会导致fp方式回不出相应的栈;混合栈情况下,fp不会记录多重混合,于是便需要dwarf回栈方式做更精确的回栈。<br/>dwarf回栈是根据pc寄存器在map表中查找对应的map信息,由于dwarf是逐级解析调用栈,所以其性能会比fp有劣化。<br/>注意:fp回栈暂不支持调优非aarch64架构的设备。 |
166| statistics_interval | int | 统计间隔,表示将一个统计周期内的栈进行汇总,单位:s。 | 为实现长时间轻量化采集,提供统计模式抓栈。如果更关注调优时的性能,只需要知道每个调用栈出现的次数和总大小,不需要知道每一次具体时间,可以使用统计模式。 |
167| startup_mode | bool | 是否抓取进程启动阶段内存。默认不抓取启动阶段内存。 | 记录进程从被appspawn拉起到调优结束这个期间内堆内存分配的信息。如果抓的是一个sa服务,需要在sa对应的cfg文件中找到拉起sa的进程名(如sa_main),将之加到此参数。 |
168| js_stack_report | int | 是否开启跨语言回栈。<br/>0:不抓取js栈。<br/>1:开启抓取js栈。 | 为方舟环境提供跨语言回栈功能。 |
169| malloc_free_matching_interval | int | 匹配间隔,单位:s,指在相应时间间隔内,将malloc和free进行匹配。匹配到的就不进行落盘。 | 在匹配间隔内,分配并释放了的调用栈不被记录,减少了抓栈服务进程的开销。此参数设置的值大于0时,就不能将statistics_interval参数设置为true。 |
170| offline_symbolization | bool | 是否开启离线符号化。<br/>true:使用离线符号化。<br/>false:使用在线符号化。 | 使用离线符号化时,根据IP匹配符号的操作在网页端(smartperf)完成,优化了native daemon的性能,减少了调优时的进程卡顿。但离线符号化会将符号表写入trace文件,导致文件大小比在线符号化时更大。 |
171| sample_interval | int | 采样大小。 | 设置此参数时开启采样模式。采样模式下对于malloc size小于采样大小进行概率性统计。调用栈分配内存大小越大,出现次数越高,被统计的几率越大。 |
172
173结果示例:
174
175开启fp回栈+跨语言回栈(其中绿色部分为js栈):
176
177![zh-cn_image_0000002379700441](figures/zh-cn_image_0000002379700441.png)
178
179开启dwarf回栈和跨语言回栈(可以展示出native -&gt; js -&gt;native的栈):
180
181![zh-cn_image_0000002346179694](figures/zh-cn_image_0000002346179694.png)
182
183开启统计模式,在此模式下,栈数据会周期性展示:
184
185![zh-cn_image_0000002379820229](figures/zh-cn_image_0000002379820229.png)
186
187开启非统计模式,在此模式下,栈数据不会周期性展示:
188
189![zh-cn_image_0000002346019934](figures/zh-cn_image_0000002346019934.png)
190
191**ftrace_plugin**:
192
1931. 参数介绍
194
195    | 参数名字 | 类型 | 参数含义 | 详细介绍 |
196    | -------- | -------- | -------- | -------- |
197    | ftrace_events | string | 抓取的trace event。 | 记录内核打点的trace event。 |
198    | hitrace_categories | string | 抓取的hitrace打点信息。 | 调用hitrace能力,获取数据以proto格式写入文件。 |
199    | hitrace_apps | string | 抓取的hitrace信息的进程。 | 设置此参数时,只有对应进程的trace信息会被记录。添加此参数时, hitrace_categories不支持添加binder,否则会导致trace数据解析异常。|
200    | buffer_size_kb | int | buffer缓存大小,单位:kB。 | hiprofiler_plugins进程读取内核事件所需要的缓存大小。推荐使用默认数值:204800。 |
201    | flush_interval_ms | int | 采集数据频率,单位:ms。 | 推荐使用默认数值:1000。 |
202    | flush_threshold_kb | int | 刷新数据大小。 | 超过threshold刷新一次数据至文件。用smartperf默认数值即可。 |
203    | parse_ksyms | bool | 是否获取内核数据。 | true:获取内核数据;false:不获取内核数据。 |
204    | trace_period_ms | int | 读取内核数据的频率。 | 用smartperf默认数值即可。 |
205
2062. 结果分析
207
208    示例命令:
209
210    ```shell
211    $ hiprofiler_cmd \
212      -c - \
213      -o /data/local/tmp/hiprofiler_data.htrace \
214      -t 10 \
215      -s \
216      -k \
217    <<CONFIG
218    request_id: 1
219    session_config {
220      buffers {
221      pages: 16384
222      }
223    }
224    plugin_configs {
225      plugin_name: "ftrace-plugin"
226      sample_interval: 1000
227      config_data {
228      ftrace_events: "binder/binder_transaction"
229      ftrace_events: "binder/binder_transaction_received"
230      buffer_size_kb: 204800
231      flush_interval_ms: 1000
232      flush_threshold_kb: 4096
233      parse_ksyms: true
234      clock: "boot"
235      trace_period_ms: 200
236      debug_on: false
237      }
238    }
239    CONFIG
240    ```
241
242    此命令读取的内核binder_transaction和binder_transaction_received数据,这两个字段同时使用,才能完整展示binder两端数据。执行命令后,通过hdc file recv将文件导出,然后拖至smartperf解析。结果示例如下图:
243
244    点击binder transaction右边的箭头,可以跳转到binder对端的进程或线程。
245
246    ![zh-cn_image_0000002316248152](figures/zh-cn_image_0000002316248152.png)
247
248**memory_plugin**:
249
2501. 参数介绍
251
252    | 参数名字 | 类型 | 参数含义 | 详细介绍 |
253    | -------- | -------- | -------- | -------- |
254    | report_sysmem_vmem_info | bool | 是否读取虚拟内存数据。 | 从/proc/vmstat节点读取内存数据。 |
255    | report_process_mem_info | bool | 是否获取进程详细内存数据,如rss_shmem,rss_file,vm_swap等。 | 从/proc/${pid}/stat节点读取内存数据。 |
256    | report_smaps_mem_info | bool | 是否获取进程smaps内存信息。 | 从/proc/${pid}/smaps节点获取进程smaps内存数据。 |
257    | report_gpu_mem_info | bool | 是否获取进程GPU使用情况。 | 读取/proc/gpu_memory节点数据。 |
258    | parse_smaps_rollup | bool | 是否从smaps_rollup节点读取smaps统计数据 | 读取/proc/{pid}/smaps_rollup节点的smaps统计数据,相比使用report_smaps_mem_info参数调优服务性能会更好(如CPU,内存使用优化)。 |
259
2602. 结果分析
261
262    ![zh-cn_image_0000002357083514](figures/zh-cn_image_0000002357083514.png)
263
264    通过DevEco-&gt;profiler-&gt;Allocation工具,选择Memory泳道,可以使用profiler的memory plugin功能。上图展示了框选时间段的进程smaps内存信息。
265
266**xpower_plugin**:
267
2681. 参数介绍
269
270    | 参数名字 | 类型 | 参数含义 | 详细介绍 |
271    | -------- | -------- | -------- | -------- |
272    | bundle_name | string | 需要进行能耗调优的进程名。 | 和/proc/节点下的进程名一致。 |
273    | message_type | XpowerMessageType | 需要获取能耗数据的类型。 | 数据类型包括:REAL_BATTERY、APP_STATISTIC、APP_DETAIL、COMPONENT_TOP、ABNORMAL_EVENTS和THERMAL_REPORT。 |
274
2752. 结果分析
276
277    ![zh-cn_image_0000002346028442](figures/zh-cn_image_0000002346028442.png)
278
279    通过DevEco-&gt;profiler-&gt;real time monitor工具,可以获取相关进程能耗数据。
280
281**gpu_plugin**:
282
283获取GPU使用率相关信息的数据。
284
285参数介绍
286
287| 参数名字 | 类型 | 参数含义 | 详细介绍 |
288| -------- | -------- | -------- | -------- |
289| pid | int | 需要进行调优的进程ID,与/proc/节点下的进程ID一致。 |
290| report_gpu_info | bool | 是否展示指定进程的GPU使用率信息 | true: 展示指定进程的GPU数据,需要设置pid。数据从/sys/class/devfreq/gpufreq/gpu_scene_aware/utilisation节点读取。<br/>false: 不展示指定进程的GPU数据。 |
291
292**cpu_plugin**:
293
294获取CPU使用率的相关信息。
295
296参数介绍
297
298| 参数名字 | 类型 | 参数含义 | 详细介绍 |
299| -------- | -------- | -------- | -------- |
300| pid | int | 需要进行调优的进程ID。 | 和/proc/节点下的进程ID一致。 |
301| report_process_info | bool | 是否展示指定进程的CPU使用率信息 | true:展示指定进程的数据,需要设置pid参数;<br/>false:不展示指定进程的数据,仅展示系统级CPU使用率数据。 |
302| skip_thread_cpu_info | bool | 是否跳过线程CPU使用率数据 | true:不展示每个线程CPU使用率的信息,开启此参数时可以降低调优服务的开销;<br/>false:展示每个线程CPU使用率的信息。 |
303
304
305## 常用命令
306
307
308### 堆内存分配调用栈数据采样记录
309
310
311com.example.insight_test_stage进程的堆内存分配操作进行抓栈,并开启fp回栈、离线符号化和统计模式。
312
313
314```shell
315$ hiprofiler_cmd \
316  -c - \
317  -t 30 \
318  -s \
319  -k \
320<<CONFIG
321 request_id: 1
322 session_config {
323  buffers {
324   pages: 16384
325  }
326 }
327 plugin_configs {
328  plugin_name: "nativehook"
329  sample_interval: 5000
330  config_data {
331   save_file: false
332   smb_pages: 16384
333   max_stack_depth: 20
334   process_name: "com.example.insight_test_stage"
335   string_compressed: true
336   fp_unwind: true
337   blocked: true
338   callframe_compress: true
339   record_accurately: true
340   offline_symbolization: true
341   startup_mode: false
342   statistics_interval: 10
343   sample_interval: 256
344   js_stack_report: 1
345   max_js_stack_depth: 10
346  }
347 }
348CONFIG
349```
350
351
352采集的数据会被保存至/data/local/tmp/hiprofiler_data.htrace文件中,该文件包含了内存泄漏分析所需的函数调用信息、线程和动态库维度内存分配情况,以及调用栈次数和分配大小聚类信息。开启离线符号化,fp回栈,统计模式均可以提升调优服务处理数据速率。
353
354
355
356抓取指定进程CPU使用率。
357
358
359对进程号为1234的进程采集CPU数据,采集时长为30s,采样周期为1000ms,调优数据传输的共享内存大小是16384个内存页,采集的数据会被保存至/data/local/tmp/hiprofiler_data.htrace文件中。
360
361
362```shell
363$ hiprofiler_cmd \
364  -c - \
365  -o /data/local/tmp/hiprofiler_data.htrace \
366  -t 30 \
367  -s \
368  -k \
369<<CONFIG
370 request_id: 1
371 session_config {
372  buffers {
373   pages: 16384
374  }
375 }
376 plugin_configs {
377  plugin_name: "cpu-plugin"
378  sample_interval: 1000
379  config_data {
380   pid: 1234
381   report_process_info: true
382  }
383 }
384CONFIG
385```
386
387
388
389## 常见问题
390
391调优出现异常。
392
393**现象描述**
394
395使用hiprofiler_cmd命令时,显示Service not started。
396
397![zh-cn_image_0000002357083914](figures/zh-cn_image_0000002357083914.png)
398
399**可能原因&amp;解决方法**
400
401调优服务未能开启,说明正在使用DevEco Studio调优或者上次调优异常退出,需要执行hiprofiler_cmd -k之后再重新执行调优命令。
402
403抓取到的trace文件为空。
404
405**现象描述**
406
407抓取到的trace文件是空的。
408
409**可能原因&amp;解决方法**
410
411需要检查生成文件的路径是否在/data/local/tmp/目录下。如果目标路径是/data/local/tmp下的一个文件夹,则尝试对文件夹执行chmod 777操作。如果是user版本使用nativehook或者network profiler抓取no debug应用,也抓不到数据(参考changelog https://gitcode.com/openharmony/docs/pulls/57419)。
412
413调优数据疑似不准确。
414
415**现象描述**
416
417hiprofiler抓取到的native heap和hidumper查看的native heap有差异。
418
419**可能原因&amp;解决方法**
420
421hidumper抓取的是进程维度内存使用情况,hiprofiler抓取到的是进程用户态通过基础库函数(malloc,mmap,realloc等,operator new也是调用的malloc)分配堆内存的数据。两者之间会有差异,差异存在于线程的内存缓存,堆内存延迟释放,加载器使用内存等。
422