0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙开发实战:【性能调优组件】

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-03-13 15:12 次阅读

简介

性能调优组件包含系统和应用调优框架,旨在为开发者提供一套性能调优平台,可以用来分析内存、性能等问题。

该组件整体分为PC端和设备端两部分,PC端最终作为deveco studio的插件进行发布,内部主要包括分为UI绘制、设备管理、进程管理、插件管理、数据导入、数据存储、 数据分析、Session管理、配置管理等模块;设备端主要包括命令行工具、服务进程、插件集合、应用程序组件等模块。设备端提供了插件扩展能力,对外提供了插件接口,基于该扩展能力可以按需定义自己的能力,并集成到框架中来,目前基于插件能力已经完成了实时内存插件,trace插件。下文会重点对设备端提供的插件能力进行介绍。

架构图

说明

下面针对设备端对外提供的插件扩展能力进行接口和使用说明。

接口说明

下面是设备端插件模块对外提供的接口:

  • PluginModuleCallbacks为插件模块对外提供的回调接口,插件管理模块通过该回调接口列表与每一个插件模块进行交互,每一个新增插件都需要实现该接口列表中的函数。

表 1 PluginModuleCallbacks接口列表

[]()

[]()[]()接口名[]()[]()类型[]()[]()描述
[]()[]()PluginModuleCallbacks::onPluginSessionStart[]()[]()int (PluginSessionStartCallback)(const uint8_tconfigData, 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)(WriterStructwriter, 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参数查看命令的使用描述信息:

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选项,用于指定配置文件;

命令展示

基础配置参数

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

命令参数说明:

  • request_id:本次请求的id
  • pages:存储trace数据的buffer大小(4 * pages kb)
  • result_file:结果输出的文件路径,与-o参数对应
  • sample_duration:抓取时长(ms),与-t参数对应

ftrace抓取场景示例

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

命令参数说明:

  • sample_interval:轮循模式下,插件上报数据的间隔时间(ms)
  • trace_period_ms:ftrace插件读取内核缓冲区数据的间隔时间(ms)
  • hitrace_time:hitrace命令行抓取时间,与hiprofiler_cmd下发的-t配置联动

内存信息抓取场景示例

内核内存信息

使用如下命令:

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 50 
  -s 
  -k 
<
进程内存使用跟踪

如配置抓取的进程名是com.ohos.mms

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

配置参数说明:

  • pid/process_name:设置抓取的进程ID或者进程名
  • max_stack_depth:抓取的栈的深度
  • smb_pages:native_daemon和native_hook进程之间存储数据的共享内存大小(4KB的倍数)
  • filter_size:只抓取大于该size的malloc数据(free不受影响)

bytrace/hitrace场景示例

运行如下命令:

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 30 
  -s 
<

hiperf场景示例

运行如下命令:

hiprofiler_cmd 
  -c - 
  -o /data/local/tmp/hiprofiler_data.htrace 
  -t 50 
  -s 
  -k 
<

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储
    +关注

    关注

    12

    文章

    3856

    浏览量

    84661
  • 内存
    +关注

    关注

    8

    文章

    2767

    浏览量

    72765
  • 鸿蒙
    +关注

    关注

    55

    文章

    1629

    浏览量

    42120
收藏 人收藏

    评论

    相关推荐

    鸿蒙实战开发学习【FaultLoggerd组件

    Faultloggerd部件是OpenHarmony中C/C++运行时崩溃临时日志的生成及管理模块。面向基于 Rust 开发的部件,Faultloggerd 提供了Rust Panic故障日志生成能力。系统开发者可以在预设的路径下找到故障日志,定位相关问题。
    的头像 发表于 03-17 20:39 132次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>实战</b><b class='flag-5'>开发</b>学习【FaultLoggerd<b class='flag-5'>组件</b>】

    鸿蒙开发实战:【蓝牙组件

    蓝牙服务组件为设备提供接入与使用Bluetooth的相关接口,包括BLE设备gatt相关的操作,以及BLE广播、扫描等功能。
    的头像 发表于 03-13 17:27 213次阅读

    鸿蒙实战开发:【FaultLoggerd组件】讲解

    Faultloggerd部件是OpenHarmony中C/C++运行时崩溃临时日志的生成及管理模块。面向基于 Rust 开发的部件,Faultloggerd 提供了Rust Panic故障日志生成能力。系统开发者可以在预设的路径下找到故障日志,定位相关问题。
    的头像 发表于 03-12 16:22 550次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>实战</b><b class='flag-5'>开发</b>:【FaultLoggerd<b class='flag-5'>组件</b>】讲解

    鸿蒙实战开发Camera组件:【相机】

    相机组件支持相机业务的开发开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。
    的头像 发表于 03-08 16:20 177次阅读
    <b class='flag-5'>鸿蒙</b><b class='flag-5'>实战</b><b class='flag-5'>开发</b>Camera<b class='flag-5'>组件</b>:【相机】

    鸿蒙实战项目开发:【短信服务】

    、OpenHarmony 多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发鸿蒙项目实战等等)鸿蒙(Harmon
    发表于 03-03 21:29

    鸿蒙ArkUI开发-Tabs组件的使用

    鸿蒙ArkUI开发-Tabs组件的使用
    的头像 发表于 01-19 16:01 433次阅读
    <b class='flag-5'>鸿蒙</b>ArkUI<b class='flag-5'>开发</b>-Tabs<b class='flag-5'>组件</b>的使用

    鸿蒙开发实战-(ArkUI)List组件和Grid组件的使用

    一系列相同宽度的列表项,连续、多行呈现同类数据,例如图片和文本。常见的列表有线性列表(List列表)和网格布局(Grid列表): 为了帮助开发者构建包含列表的应用,ArkUI提供了List组件和Grid
    发表于 01-18 20:18

    鸿蒙开发-ArkUI框架实战【日历应用 】

    对于刚刚接触OpenHarmony应用开发开发者,最快的入门方式就是开发一个简单的应用,下面记录了一个日历应用的开发过程,通过日历应用的开发
    发表于 01-17 21:37

    鸿蒙开发-ArkUI 组件基础

    1 组件介绍 组件(Component)是界面搭建与显示的最小单位,HarmonyOS ArkUI声明式开发范式为开发者提供了丰富多样的UI组件
    发表于 01-17 19:31

    鸿蒙开发OpenHarmony组件复用案例

    \\\\common.d.ts的自定义组件的生命周期里定义了aboutToReuse方法,如下: 自定义组件的生命周期回函数用于通知用户该自定义组件的生命周期,这些回
    发表于 01-15 17:37

    鸿蒙开发基础-Web组件之cookie操作

    }) ... } ... 本文章主要是对鸿蒙开发当中ArkTS语言的基础应用实战,Web组件里的cookie操作。更多的鸿蒙应用
    发表于 01-14 21:31

    免费学习鸿蒙(HarmonyOS)开发,一些地址分享

    。 分别有ArkTS语言、ArkUI声明式UI开发、Stage模型、北向和南向的开发等等鸿蒙入门到实战的内容。
    发表于 01-12 20:48

    鸿蒙基础开发实战-(ArkTS)像素转换

    的使用。通过像素转换案例,向开发者讲解了如何使用像素单位设置组件的尺寸、字体的大小以及不同像素单位之间的转换方法。更多鸿蒙4.0的学习,可以前往主页学习或前往《鸿蒙4.0
    发表于 01-11 16:53

    HarmonyOS NEXT工具Smart Perf Host高效使用指南

    了测试、、分析一站式服务,**接下来让我们一起来看Smart Perf如何解决开发性能问题。 在Smart Perf工具全家桶中,Smart Perf Host主要提供性能
    发表于 11-09 08:35

    鸿蒙 OS 应用开发初体验

    的操作系统平台和开发框架。HarmonyOS 的目标是实现跨设备的无缝协同和高性能。 DevEco Studio 对标 Android Studio,开发鸿蒙 OS 应用的 IDE。
    发表于 11-02 19:38