• Qcom perflock学习笔记 Hello


    一、perflock简介

    perflock是Qcom平台在特定场景下进行特定的参数配置,以达到性能功耗均衡的一个服务框架。


    二、实现与使用

    1. 实现框架

    (1) 在打包在 vendor.img 的QTI相关的代码,通过动态加载 libqti-perfd-client.so(不应该被OEM厂商使用),这个库中通过调用HIDL Client模块中的函数,通过hwbinder与HIDL Server(PerfHAL)通信。

    (2) 打包在 system.img 的OEM代码,Java层通过调用 import Android.util.BoostFramework 然后调用其中的函数,通过JNI的方式调用到HIDL Client中的函数。Native层的代码通过动态链接 libqti-perfd-client_system.so 库,库函数会调用到HIDL Client中的函数。最后统一由HIDL Client通过hwbinder的方式和HIDL Server(PerfHAL)通信。

    (3) HIDL Server(PerfHAL) 中有 perfboostsconfig.xml 配置文件,自己也会根据配置文件下发命令。并接收HIDL Client通过hwbinder发来的请求,会将所有请求链接到一个list上,然后通过写sysfs的形式写给内核。

    2. Java层中使用perflock大致步骤

    (1) 在system分区中通过如下方式使用Perflock
    a. import android.util.BoostFramework
    b. 创建 BoostFramework 类对象
    c. 使用 perfLockAcquire 提交优化请求
    d. 使用 perfLockRelease / perfLockReleaseHandler 来释放优化请求
    e. 使用 perfLockAcqAndRelease 来释放前一个优化请求和提交现有优化请求
    f. 为基于hint的请求使用 perfHint

    下面有Java层的使用举例。

    3. Native层中使用perflock大致步骤

    a. 在app的makefile中 LOCAL_SHARED_LIBRARIES 字段中必须添加 libdl 和 libqti-perfd-client_system 两个库。在 LOCAL_C_INCLUDES 中添加 vendor/qcom/proprietary/commonsys/perf-core/mpctl-client/mp-ctl.h(T之前版本路径在 vendor/qcom/proprietary/android-perf/mp-ctl/mp-ctl.h)
    b. 使用文件中 #include <dlfcn.h>,通过 dlopen 打开 libqti-perfd-client_system.so,然后通过 dlsym 取出库中的 perf_lock_acq、perf_lock_rel、perf_hint 函数,然后保存 perf_lock_acq、perf_hint 返回的handle值,然后使用 perf_lock_acq 提交优化请求,使用 perf_lock_rel 来释放请求锁定,使用 perf_lock_acq_rel 释放之前、请求的锁定和提交本次请求。使用 perf_hint 来请求hint触发器。
    c. 在清理时使用 dlclose 来unload动态库。

    下面有Native层的使用举例。

    4. perflock函数common参数说明
    perflock acquire 需要 handle, duration, <opcode value pair> 作为参数,
    a. handle 用来辨别client的请求。client在请求一个perflock的时候,server会返回一个handle, 在释放perflock时client需要传入这个handle.
    b. duration 用来指定最大的超时时间,但是ms,大于0是有限期的,到期后自动释放,0表示无限期,需要显式的调用release进行释放。
    c. opcode 是一个32bit int值,定义在 vendor/qcom/proprietary/android-perf/mp-ctl/PerfController.h 中,如 MPCTLV3_TOGGLE_POWER_COLLAPSE。
    d. value 新版本的opcode需要附带一个 32 位的值,值需要是十六进制格式,因为当前 perfd 将每个值视为十六进制。


    三、配置文件

    1. perfboostsconfig.xml

    (1) perfhint宏和opcode宏定义在 vendor/qcom/proprietary/android-perf/mp-ctl/PerfController.h 中,举例:

    //perf hints
    enum {
        VENDOR_HINT_FIRST_LAUNCH_BOOST = 0x00001081,
        VENDOR_HINT_FPS_UPDATE = 0x00001094,
        VENDOR_HINT_PICARD_GPU_DISPLAY_MODE = 0x00001098,
        MPCTLV3_PID_AFFINE = 0x42C20000,
        MPCTLV3_GPU_DISABLE_GPU_NAP = 0X4281C000,
         MPCTLV3_DISPLAY_EARLY_WAKEUP_HINT = 0x41C0C000,
        ...
    };
    
    //opcode
    enum {
        MPCTLV3_SCHED_BOOST = 0x40C00000,
        MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0 = 0x40804000,
        MPCTLV3_SCHED_WINDOW_TICKS_UPDATE = 0x40CA4000,
        MPCTLV3_BUS_DCVS_MEMLAT_SAMPLE_MS = 0x43468000,
        ...
    };

    opcode 各字段的解释:

    bit30-bit31:perfLock 的版本:
    bit22-bit28:major type
    bit13: mapping type for the value
    bit14-bit19:minor type
    bit8 -bit11:cluster which perfLock applied on
    bit4 - bit6:core within the cluster
    The rest of the bits are reserved

    (2) 配置文件位置 /vendor/qcom/proprietary/perfcore/configs//[chipset]/perfboostsconfig.xml,打包到机器中的位置 /vendor/etc/perf/perfboostsconfig.xml,配置文件通常由以下字段组成:

    Item          Description
    -----------------------------------------------------------------------
    ID            boosts id;ID线性增加;不要修改或在两者之间添加
    Type          boost type
    Enable        boost是否被使能
    Timeout       boost持续时间,单位ms
    Target        目标平台名,若是在你的tragetconfig.xml中不只定义一个target,必须为每个目标添加配置标签,Perflock 会根据目标名称区分不同的 boost 策略。
    Resources     两个值一组,第一个值是opcode,第二个值是此操作的值。
    Resolution    如果您需要针对一台目标设备的不同分辨率进行boost,比如Resolution="1080p",请使用分辨率字段来实现(可选配置项)
    Kernel        指定内核版本(可选配置项)
    FPS           用于支持不同帧率下的boost配置

    举例1:

    <Config
        Id="0x00001081" Type="1" Enable="false" Timeout="2000" Target="pname"
            Resources="0x40C00000, 0x1, 0x40804000, 0xFFF, ..." />

    解释:在launch场景,垂直或水平滑动,对pname平台的机器使能sched boost,并且将大核的第一个CPU的最大频点放开(限制0xFFF=4095MHz),持续时间是2000ms。但是这个feture是关闭的。

    举例2:

    <!-- 90fps -->
    <Config
        Id="0x00001094" Type="90" Enable="true" Target="pname" Timeout="0"
            Resources="0x40CA4000, 3, 0x43468000, 12" />

    解释:在更新帧率到90fps时,将 window tick update的参数设置为3,memlat采样周期设置为12ms,永久保持。

    举例3:

    <Config
        Id="0x00001098" Type="0" Enable="true" Target="pname1,pname2" Timeout="2000" Fps="120"
            Resources="0x42C20000, 1, 0x4281C000, 13, 0x41C0C000, 0" />

    解释:这是对共代码的两个平台的机器在120fps时的配置。

    2. commonresourceconfigs.xml

    (1) vendor/qcom/proprietary/android-perf/mp-ctl/PerfController.h 中有指定

    enum major_resource_opcode {
        ...
        SCHED_MAJOR_OPCODE, /* 0x3 */
    };
    
    enum minor_resource_opcode {
        ...
        SCHED_START_INDEX = CPUFREQ_START_INDEX + MAX_CPUFREQ_MINOR_OPCODE,
        SCHED_BOOST_OPCODE = 0,    /* 0x0 */
        SCHED_PREFER_IDLE_OPCODE,    /* 0x1 */
        SCHED_MIGRATE_COST_OPCODE,    /* 0x2 */
        ...
    };

    (2) 位置 vendor/qcom/proprietary/android-perf/configs/common/commonresourceconfigs.xml,打包到机器中的位置/vendor/etc/perf/commonresourceconfigs.xml。

    该文件是一个通用配置文件,包含了 Major Type 和 Minor Type 的定义操作码位,它们都唯一标识了物理资源。比如要找 MPCTLV3_SCHED_BOOST 这个opcode写的是哪个文件,可以在 PerfController.h 中检索 SCHED_BOOST,然后得到 major_resource_opcode=0x3,minor_resource_opcode=0x0,然后就可以找到其对应的资源sysfs文件:

    <Major OpcodeValue="0x3" />
        <Minor OpcodeValue="0x0" Node="/proc/sys/kernel/sched_boost" />
        <Minor OpcodeValue="0x1" Node="/proc/sys/kernel/sched_prefer_idle" Supported="no" />
        <Minor OpcodeValue="0x2" Node="/proc/sys/kernel/sched_migration_cost_ns" />
        ...

     比如 MPCTLV3_SCHED_BOOST = 0x40C00000, 按上面opcode各字段的解释展开,就是"10 0000011(maior) 00 000000(minor) 00000000000000", major=0000011, minor=000000, 操作的配置文件就是 /proc/sys/kernel/sched_boost.

    3. perfconfigstore.xml

    此文件主要是一些feature的开关配置文件,位置 vendor/qcom/proprietary/android-perf/configs/<pname>/perfconfigstore.xml,打包到机器中的位置/vendor/etc/perf/perfconfigstore.xml,Value="false"表示关闭此feature。"XXX_dup" 用于覆盖系统级别的属性。

    <PerfConfigsStore>
        <PerfConfigs>
            <!--Vendor Properties -->
            <Prop Name="vendor.iop.enable_uxe" Value="1" />
            <Prop Name="vendor.debug.enable.lm" Value="true" />
            <Prop Name="vendor.perf.iop_v3.enable" Value="true" Target="pname1,pname2" />
            <Prop Name="vendor.perf.topAppRenderThreadBoost.enable" Value="false" Target="pname1,pname2" />

    四、相关API介绍

    1. perflock acquire

    (1) Java
    //可变参数函数,list是<opcode,value>对,成功返回非0的handle,失败返回-1
    public int perfLockAcquire(int duration, int... list)
    
    (2) Native
    int perf_lock_acq(int handle, int duration, int list[], int numArgs)

    注:
    a. 若请求的是频率,value的单位必须是MHz,例如1.5GHz值是1500MHz,对应16进制是0x6DC。
    b. 若指定时间,value的单位需要是ms,例如50ms是0x32
    c. 对于其它的 perflocks,应指定预期值。
    d. 对于 MAX_CORE_ONLINE 和 INTERACTIVE_TIMER_RATE ONDEMAND_TIMER_RATE 等某些 perflock,这些值是绝对值。 例如,如果要求最多只有 1 个内核在线,则指定的值为 0xFF。使用新的 perflock API,指定的值为 0x1。

    2. perflock release

    (1) Java
    public int perfLockRelease()
    public int perfLockReleaseHandler(int handle)
    
    (2) Native
    int perf_lock_rel(int handle)

    传参-1(0xFFFFFFFF)表示释放所有的perflock。成功返回0失败返回-1。若是Acquire时设置了持续时间,就不需要调用Release。

    3. acquire and release

    (1) Java
    public int perfLockAcqAndRelease(int handle, int duration, int numArgs, int reserveNumArgs, int... list)
    
    (2) Native
    int perf_lock_acq_rel(int handle, int duration, int list[], int numArgs, int reserveNumArgs)

    释放先前的 perflock,获取新的 perflock 并等待 int 返回。 这将减少来自系统的一次binder call。
    参数:
    handle:句柄
    duration:保持锁定的时间,单位ms
    numArgs:列表数组的元素个数
    reserveNumArgs:用于客户端 pid/tid 内部用途的参数;0
    list:opcodes 和 value 数组
    返回值:
    成功返回非0的handle值,失败返回-1.

    4. perf hint

    (1) Java
    public int perfHint(int hint, String userDataStr, int userData1, int userData2)
    public int perfHint(int hint, String userDataStr)
    public int perfHint(int hint, String userDataStr, int userData)
    
    (2) Native
    int perf_hint(int hint, char *pkg, int duration, int type)

    后两个只是第一个的变更参数的重载函数,调用的还是函数1。
    参数:
    hint:hint id
    userDataStr: 触发hint的app的包名
    userData1(userData):持续时间
    userData2: 区分类似的动作,例如水平滚动与垂直滚动
    返回值:
    成功返回非0 handle值,失败返回-1.

    可以直接申请场景的perflock,该函数根据 hint id 和 hit type 查找xml文件中指定内容,然后使用使用xml文件中的指定参数发起 perflock 请求。通常需要的参数为:hint_id, package_name, duration, hint_type/reserved
    hint_id:识别是哪个action,如launch, scroll
    package_name:触发这个hint的app包名
    duration:hint的持续时间
    hint_type(Reserved): 区分类似的动作,例如水平滚动与垂直滚动.

    注:若定义hint需要在 VENDOR_HINT_START / VENDOR_HINT_END 之间进行定义。

    5. Perf Hint acquire and release

    (1) Java
    public int perfHintAcqRel(int handle, int hint, String pkg_name, int duration, int type, int numArgs, int... list)
    
    (2) Native
    int perf_hint_acq_rel(int handle, int hint, const char *pkg, int duration, int type, int numArgs, int list[])

    参数:
    handle: 用户传入的要释放的hint的handle值。
    hint:新hint的hint id,如 launch, scroll 等。
    pkg_name: 触发这个hint的app包名。
    duration:此hint持续时间
    type(reserved): 区分类似的动作,例如水平滚动与垂直滚动.
    numArgs: 内部参数,0。
    list: 内部参数,null。

    成功返回非0的handle值,失败返回-1。释放先前的 perflock hint 然后申请一个新的 perflock 并等待返回,这减少了一次来自system的hardware binder call。

    6. Perf hint renew

    (1) Java
    public int perfHintRenew(int handle, int hint, String pkg_name, int duration, int hintType, int numArgs, int... list)
    
    (2) Native
    int perf_hint_renew(int handle, int hint, const char *pkg, int duration, int type, int numArgs, int list[])

    延长现有的perf hint。handle是要renew的handle,用handle来跟踪每一个perf request。其它参数和上面一样。成功返回非0的handle值,失败返回-1.

    7. Perf event

    (1) Java
    public void perfEvent(int eventId, String pkg_name, int numArgs, int... list)
    
    (2) Native
    void perf_event(int eventId, const char *pkg, int numArgs, int list[])

    参数:
    eventId: 就是hint id
    pkg_name: 触发这个hint的app包名。
    numArgs: 内部参数,0。
    list: 内部参数,null。

    低延迟API,提交hint请求但并不等待返回,这将减少一次来自system的binder call.

    五、使用Demo

    1. Java中请求中核至少2个核是online的,并将中核最小频率拉到1.5 GHz。注意,不需要使用端调用perflockRelease,因为3s后会自动调用。

    import android.util.BoostFramework;
    BoostFramework mPerf = new BoostFramework();
    int duration = 3000;
    int list[];
    list[0] = MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG;
    list[1] = 2;
    list[2] = MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0
    list[3] = 1500;
    mPerf.perfLockAcquire(duration, list);

    2. Java中请求中核至少在线3个核,设置的超时时间是5s,但是在关键区执行完后就立即release。然后请求中核至少在线2个核,设置的超时时间是3s,但是在关键区执行完后就立即release。

    BoostFramework mPerf = new BoostFramework();
    BoostFramework sPerf = new BoostFramework();
    int list[];
    list[0] = MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG;
    list[1] = 3;
    mPerf.perfLockAcquire(5000, list);
    //持有 PerfLock 的关键部分
    mPerf.perfLockRelease();
    
    // other code in between
    list[0] = MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG;
    list[1] = 2;
    sPerf.perfLockAcquire(3000, list);
    //持有 PerfLock 的关键部分
    sPerf.perfLockRelease();

    3. Native代码中的请求

    (1) makefile中

    LOCAL_SHARED_LIBRARIES := libqti-perfd-client_system
    LOCAL_C_INCLUDES := vendor/qcom/proprietary/android-perf

    (2) 源码

    #include <dlfcn.h>
    #include "mp-ctl/mp-ctlh"
    
    #define acq_func_type int(*)(int, int, int*,int)
    #define rel_func_type int(*)(int)
    
    static void *qcopt_handle;
    static int (*perf_lock_acq)(int handle, int duration, int list[], int numArgs);
    static int (*perf_lock_rel)(int handle);
    static int (*perf_hint)(int, char *, int, int);
    static int perf_lock_handle;
    
    char opt_lib_path[PATH_MAX] = "xxx/libqti-perfd-client_system.so";
    
    if((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
        error_out();
    } else {
        perf_lock_acq = (acq_func_type)dlsym(qcopt_handle, "perf_lock_acq");
        perf_lock_rel = (rel_func_type)dlsym(qcopt_handle, "perf_lock_rel");
        perf_hint = dlsym(qcopt_handle, "perf_hint");
    }
    int perf_lock_opts[2] = {MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG ,0x2};
    perf_lock_handle = perf_lock_acq(perf_lock_handle, 0, perf_lock_opts, 2); //duration=0表示无限期
    //持有PerfLock的关键区
    perf_lock_rel(perf_lock_handle);

    六、相关DEBUG方法

    1. 使能调试:echo vendor.debug.trace.perf=1 >> /system/build.prop,然后 reboot,perf模块相关信息会产生在logcat和systrace中。logcat中检索 "ANDR-PERF-MPCTL:" 或 "perf_lock_acq:", 在Systrace中也检索 "perf_lock_acq:"

    trace上,在 vendor.qti.hardware.perf-hal-service 进程条目下显示如下,通过binder跳转看到Client信息。

    perf_lock_acq: client_pid=1344, client_tid=2809, inupt handle=0, duration=9 ms, num_args=4, list=0x40800000 0x5DC 0x42804000 0x0 

    logcat log上:

    14:59:17.463  1360  1360 E ANDR-PERF-MPCTL: perf_lock_acq: client_pid=1344, client_tid=2811, inupt handle=0, duration=9 ms, num_args=4, list=0x40800000 0x5DC 0x42804000 0x0 
    14:59:17.463  1360  1360 E ANDR-PERF-MPCTL: perf_lock_acq: output handle=102 //这个handle是唯一的单调递增的

    若是不想重启可以:

    adb shell setprop vendor.debug.trace.perf 1
    adb shell stop perf-hal-2-3
    adb shell start perf-hal-2-3

    若是想在源码中添加,可以:

    /device/qcom/taro/BoardConfig.mk:
    PRODUCT_SYSTEM_PROPERTIES += vendor.debug.trace.perf=1

    2. 要想要更多调试信息,将 vendor/qcom/proprietary/android-perf/mp-ctl/ 下的 makefile 中的 QC_DEBUG 表示使能。然后在logcat log中检索 "ANDR-PERF-MPCTL:"。

    3. 支持 dumpsys vendor.perfservice 来dump active的request。打印依次是 Client Pid、Client Pkg Name、Boost Duration、Boost Parameters:

    # dumpsys vendor.perfservice
    ------------------------------------------------------------Active Clients-----------------------------------------------------------
     Pid(Tid)      | PkgName                                                   | Duration     | OpCodes
    -------------------------------------------------------------------------------------------------------------------------------------
     13314(13315)  | /vendor/bin/hw/vendor.qti.hardware.perf-hal-service       | 0            | 0x40cd0000 13315    0x40cf0000 13315    0x40cd0000 13314    0x40cf0000 13314
     13314(13315)  | /vendor/bin/hw/vendor.qti.hardware.perf-hal-service       | 2147483647   | 0x40ca4000 2    0x43468000 8    0x40c74000 15    0x40408000 3    0x40cc8000 119

    参考:
    80-pk882-53_b_perflock_overview.pdf
    80-NT384-4_PERFLOCK IN ANDROID T.pdf

  • 相关阅读:
    HDU 4123 Bob’s Race 树的直径+ST表
    acm 2015北京网络赛 F Couple Trees 树链剖分+主席树
    acm java入门(转载)
    java水题集
    南昌网络赛C.Angry FFF Party
    eclipse 安装
    eclipse jdk安装
    树链剖分总结
    P
    L
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/16670866.html
Copyright © 2020-2023  润新知