# 性能调优组件 - [简介](#section6874544183112) - [架构图](#section1514713331342) - [目录](#section1742612449345) - [说明](#section2165102016359) - [接口说明](#section558917318367) - [使用说明](#section681316903611) - [调测验证](#section35362541215) - [hiprofiler_cmd 使用说明](#section35362541216) - [参数说明](#section35362541290) - [命令展示](#section35362541500) - [基础配置参数](#section35362541219) - [ftrace抓取场景示例](#section35362541220) - [内存信息抓取场景示例](#section35362541221) - [内核内存信息](#section35362541222) - [虚拟内存统计](#section35362541223) - [进程内存使用跟踪](#section35362541224) - [bytrace/hitrace场景示例](#section35362541225) - [hiperf场景示例](#section35362541226) - [相关仓](#section1293495681320) ## 简介 性能调优组件包含系统和应用调优框架,旨在为开发者提供一套性能调优平台,可以用来分析内存、性能等问题。 该组件整体分为PC端和设备端两部分,PC端最终作为deveco studio的插件进行发布,内部主要包括分为UI绘制、设备管理、进程管理、插件管理、数据导入、数据存储、 数据分析、Session管理、配置管理等模块;设备端主要包括命令行工具、服务进程、插件集合、应用程序组件等模块。设备端提供了插件扩展能力,对外提供了插件接口,基于该扩展能力可以按需定义自己的能力,并集成到框架中来,目前基于插件能力已经完成了实时内存插件,trace插件。下文会重点对设备端提供的插件能力进行介绍。 ## 架构图 ![](figures/zh-cn_image_0000001162598155.png) ## 目录 ``` /developtools/profiler ├── device # 设备侧代码目录 │ ├── base # 基础功能代码 │ │ ├── include # 基础功能的头文件代码目录 │ | ├── src # 基础功能的源文件代码目录 │ | └── test # 基础功能的测试代码目录 │ ├── cmds # 对外命令行模块的代码 │ | ├── include # 对外命令行模块的头文件代码目录 │ | ├── src # 对外命令行模块的源文件代码目录 │ | └── test # 对外命令行模块的测试代码目录 │ └── plugins # 插件代码目录 │ ├── api # 插件模块对外提供的接口文件代码目录 │ | ├── include # 插件模块对外提供的接口头文件代码目录 │ | └── src # 插件模块对外提供的接口源文件代码目录 │ ├── memory_plugin # 内存插件模块代码目录 │ | ├── include # 内存插件模块头文件代码目录 │ | ├── src # 内存插件模块源文件代码目录 │ | └── test # 内存插件模块测试代码目录 │ └── trace_plugin # trace插件模块代码目录 │ ├── include # trace插件模块头文件代码目录 │ ├── src # trace插件模块源文件代码目录 │ └── test # trace插件模块测试代码目录 ├── host # 主机侧代码目录 │ └── ohosprofiler # 主机侧调优模块代码目录 │ └── src # 主机侧调优模块源文件代码目录 ├── protos # 项目中的proto格式文件的代码目录 │ └── innerkits # 对内部子系统暴露的头文件存放目录 │ └── builtin # JS应用框架对外暴露JS三方module API接口存放目录 ├── trace_analyzer # bytrace解析模块的代码目录 │ ├── include # bytrace解析模块的公共头文件存放目录 │ └── src # bytrace解析模块功能源文件存放目录 ├── interfaces # 项目中接口的代码目录 │ ├── innerkits # 模块间接口的代码目录 │ └── kits # 对外提供接口存放目录 ``` ## 说明 下面针对设备端对外提供的插件扩展能力进行接口和使用说明。 ### 接口说明 下面是设备端插件模块对外提供的接口: - PluginModuleCallbacks为插件模块对外提供的回调接口,插件管理模块通过该回调接口列表与每一个插件模块进行交互,每一个新增插件都需要实现该接口列表中的函数。 **表 1** PluginModuleCallbacks接口列表

接口名

类型

描述

PluginModuleCallbacks::onPluginSessionStart

int (*PluginSessionStartCallback)(const uint8_t* configData, uint32_t configSize);

  • 功能:

    插件会话开始接口,开始插件会话时会被调用,用来下发插件配置

  • 输入参数:

    configData:配置信息内存块起始地址

    configSize:配置信息内存块字节数

  • 返回值:

    0:成功

    -1:失败

PluginModuleCallbacks::onPluginReportResult

int (*PluginReportResultCallback)(uint8_t* bufferData, uint32_t bufferSize);

  • 功能:

    插件结果上报接口类型,当任务下发后,框架采集任务会周期性调用此接口请求回填数据

  • 输入参数:

    bufferData: 存放结果的内存缓冲区起始地址

    bufferSize: 存放结果的内存缓冲区的字节数

  • 返回值:

    大于0:已经填充的内存字节数

    等于0:没有填充任何内容

    小于0:失败

PluginModuleCallbacks::onPluginSessionStop

int (*PluginSessionStopCallback)();

  • 功能:

    采集会话结束接口

  • 返回值:

    0:成功

    -1:失败

PluginModuleCallbacks::onRegisterWriterStruct

int (*RegisterWriterStructCallback)(WriterStruct* writer);

  • 功能:

    采集框架注册写数据接口,当插件管理模块向插件注册此接口,插件可以主动调用write句柄,进行写入数据

  • 输入参数:

    writer 写者指针

  • 返回值:

    0:成功

    -1:失败

- WriterStruct是上面onRegisterWriterStruct接口中的参数,主要实现写数据接口,将插件中采集的数据通过该接口进行写入。 **表 2** WriterStruct接口列表

接口名

类型

描述

WriterStruct::write

long (*WriteFuncPtr)(WriterStruct* writer, const void* data, size_t size);

  • 功能:

    写接口,将插件中采集的数据通过writer进行写入

  • 输入参数:

    writer:写者指针

    data:数据缓冲区首字节指针

    size: 数据缓冲区的字节数

  • 返回值:

    0:成功

    -1:失败

WriterStruct::flush

bool (*FlushFuncPtr)(WriterStruct* writer);

  • 功能:

    触发数据上传接口

  • 输入参数:

    writer:写者指针

  • 返回值:

    true:成功

    false:失败

- 下面是插件模块对外提供的总入口,主要包括表1中的插件模块回调函数以及插件名称、插件模块需要申请的内存大小。 **表 3** PluginModuleStruct接口列表

接口名

类型

描述

PluginModuleStruct::callbacks

PluginModuleCallbacks*

功能:定义插件回调函数列表

PluginModuleStruct::name

C style string

功能:定义插件名称

PluginModuleStruct::resultBufferSizeHint

uint32_t

功能:用于提示插件管理模块调用数据上报接口时使用的内存缓冲区字节数

### 使用说明 下面介绍在设备端基于性能调优框架提供的插件能力,新增一个插件涉及到的关键开发步骤: 1. 编写proto数据定义文件_plugin\_data.proto_,定义数据源格式,数据源格式决定了插件上报哪些数据: ``` message PluginData { int32 pid = 1; string name = 2; uint64 count1 = 3; uint64 count2 = 4; uint64 count3 = 5; ...... } ``` 2. 编写数据源配置文件_plugin\_config.proto_,采集的行为可以根据配置进行变化,可以设置数据源上报间隔等信息: ``` message PluginConfig { int32 pid = 1; bool report_interval = 2; int report_counter_id_1 = 3; int report_counter_id_2 = 4; ...... } ``` 3. 定义PluginModuleCallbacks实现插件回调接口;定义PluginModuleStruct类型的g\_pluginModule全局变量,注册插件信息。 ``` static PluginModuleCallbacks callbacks = {     PluginSessionStart,     PluginReportResult,     PluginSessionStop, }; PluginModuleStruct g_pluginModule = {&callbacks, "test-plugin", MAX_BUFFER_SIZE}; ``` 4. 通过PluginSessionStart(名字可以自己定义)实现插件回调接口列表的onPluginSessionStart接口,主要处理插件的开始流程。 ``` int PluginSessionStart(const uint8_t* configData, uint32_t configSize) { ...... return 0; } ``` 5. 通过PluginReportResult(名字可以自己定义)实现插件回调接口列表的onPluginReportResult接口,将插件内部采集的信息通过该接口进行上报: ``` int PluginReportResult(uint8_t* bufferData, uint32_t bufferSize) { ...... return 0; } ``` 6. 通过PluginSessionStop(名字可以自己定义)实现插件回调接口列表的onPluginSessionStop接口,主要进行插件停止后的操作流程。 ``` int PluginSessionStop() { ...... return 0; } ``` 7. 编写proto gn构建脚本, 生成protobuf源文件,protobuf源文件编译生成目标文件: ``` action("plugin_cpp_gen") { script = "${OHOS_PROFILER_DIR}/build/protoc.sh" //依赖的编译工具链 sources = [ //定义的插件相关的proto文件,比如插件配置文件、插件数据对应的proto文件 "plugin_data.proto", "plugin_config.proto", ] outputs = [ //通过protoc编译生成的结果文件 "plugin_data.pb.h", "plugin_data.pb.cc", "plugin_config.pb.h", "plugin_config.pb.cc", ] args = [ "--cpp_out", "$proto_rel_out_dir", "--proto_path", rebase_path(".", root_build_dir), ] deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})", ] } ohos_source_set("plug_cpp") { //将定义的proto文件生成cpp文件 deps = [ ":plugin_cpp_gen", ] public_deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", ] include_dirs = [ "$proto_out_dir" ] sources = [ //目标plug_cpp中包括的源文件 "plugin_data.pb.h", "plugin_data.pb.cc", "plugin_config.pb.h", "plugin_config.pb.cc", ] } ``` 8. 编写插件GN构建脚本: ``` ohos_shared_library("***plugin") { output_name = "***plugin" sources = [ "src/***plugin.cpp", //插件中的源文件 ] include_dirs = [ "../api/include", "${OHOS_PROFILER_DIR}/device/base/include", ] deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc_lib", "${OHOS_PROFILER_DIR}/protos/types/plugins/**:plug_cpp", //上面ohos_source_set中生成的plug_cpp ] install_enable = true subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" } ``` ### 调测验证: 插件动态库生成后,可以自己编写测试代码,通过dlopen加载动态库,并调用上面代码中实现的插件模块回调函数进行验证。 ``` int main(int argc, char** argv) { void* handle; PluginModuleStruct* memplugin;     handle = dlopen("./libplugin.z.so", RTLD_LAZY); //动态打开上面生成的插件动态库     if (handle == nullptr) {         HILOGD("dlopen err:%s.", dlerror());         return 0;     } memplugin = (PluginModuleStruct*)dlsym(handle, "g_pluginModule"); //获取开发步骤3中定义的g_pluginModule全局变量 //check memplugin->callbacks // 通过该指针调用上面开发步骤3中定义的回调函数 return 0; ``` ## hiprofiler_cmd 使用说明 ### 参数说明 执行hiprofiler_cmd 为调优业务的离线命令行抓取工具,具体使用方法及命令行参数介绍如下。 可以使用`-h`或者`--help`参数查看命令的使用描述信息: ```sh hiprofiler_cmd -h help : --getport -q : get grpc address --time -t : trace time --out -o : output file name --help -h : make some help --list -l : plugin list --start -s : start dependent process --kill -k : kill dependent process --config -c : start trace by config file ``` 其余参数使用说明如下: * `-q`或者`--getport`选项,用于查询服务的端口信息; * `-t`或者`--time`选项,用于指定抓取时间,单位是秒; * `-o`或者`--out`选项,用于指定输出的离线数据文件名; * `-h`或者`--help`选项,用于输出帮助信息; * `-l`或者`--list`选项,用于查询插件列表; * `-s`或者`--start`选项,用于启动依赖的进程; * `-k`或者`--kill`选项,用于关闭依赖的进程; * `-c`或者`--config`选项,用于指定配置文件; ### 命令展示 #### 基础配置参数 ```sh hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 50 \ -s \ -k \ < ```sh hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 50 \ -s \ -k \ < ##### 内核内存信息 使用如下命令: ```sh hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 50 \ -s \ -k \ < 使用如下命令: ```sh hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 50 \ -s \ -k \ < 如配置抓取的进程名是com.ohos.mms ``` sh hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 50 \ -s \ -k \ < 运行如下命令: ``` hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 30 \ -s \ < 运行如下命令: ``` sh hiprofiler_cmd \ -c - \ -o /data/local/tmp/hiprofiler_data.htrace \ -t 50 \ -s \ -k \ < [研发工具链子系统]() **developtools\_profiler** [developtools\_hdc](https://gitee.com/openharmony/developtools_hdc) [developtools\_bytrace](https://gitee.com/openharmony/developtools_bytrace)