Qualcomm Linux(QCS6490/QCS5430) 性能指南(六)

自定义配置

自定义 BWMON 调节器

你可以根据功耗和性能需求,从 kernel_platform/kernel/arch/arm64/boot/dts/qcom/sc7280.dtsi 文件中自定义 bwmon_opp_table 以进行 LLCC 和 DDR 投票。
该表包含 DDR 和 LLCC 的频率级别,每个级别根据流量转换为 LLCC 和 DDR 投票。
例如,以下 DTSI 条目根据 CPU 流量在 LLCC 到 DDR 之间投票,对应于 200 MHz,因为 800000 / w(其中 w = 4)等于 200,000。

llcc_bwmon_opp_table: opp-table {
    compatible = "operating-points-v2";
    opp-0 {
        opp-peak-kBps = <800000>;
    };
};

以下 DTSI 条目根据 CPU 和 LLCC 之间的 CPU 流量在 LLCC 上投票,对应于 150 MHz,因为 2400000 / w(其中 w = 16)等于 150,000:

cpu_bwmon_opp_table: opp-table {
    compatible = "operating-points-v2";
    opp-0 {
        opp-peak-kBps = <2400000>;
    };
};

在此示例中,w 表示你可以在一个周期内写入的字节数。

  • 对于 DDR,此值为 4。每个通道可以在每个周期执行两个事务(DDR 内存),每个事务为 2 字节。
  • 对于 LLCC,此值为 16。

自定义 Perflock

你可以运行 Perflock API,使用不同的调优参数执行用例,并调试 Perflock 问题。

Perflock API

要从用户空间软件中使用 Perflock API,请按照以下步骤操作:

  1. 在源文件中包含动态链接头文件:#include <dlfcn.h>。
  2. 使用 dlopen 加载库(libqti-perfd-client.so)。使用系统属性
    ro.vendor.extension_library。
  3. 使用 dlsym 加载 perf_lock_acq() 和 perf_lock_rel() 符号。
  4. 声明一个整数变量以存储 perf_lock_acq() 的返回值。
  5. 使用所需的资源操作码和值对定义 perf_lock_opts。
  6. 使用指定的优化选项调用 perf_lock_acq() 以获取锁。
  7. 使用 perf_lock_rel() 释放锁。
  8. 在清理时使用 dlclose 卸载库。

以下示例代码显示了 Perflock API 的使用:

#include <dlfcn.h>
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_lock_handle;
char opt_lib_path[PATH_MAX] = {0};
if (property_get("ro.vendor.extension_library", opt_lib_path, NULL) != 0) {
	if ((qcopt_handle = dlopen(opt_lib_path, RTLD_NOW)) == NULL) {
		error_out();
	} else {
		perf_lock_acq =  (int (*)(int, int, int *, int))dlsym(qcopt_handle, "perf_lock_acq");
		perf_lock_rel = (int (*)(int))dlsym(qcopt_handle, "perf_lock_rel");
	}
}
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); 
:
:
// Code requiring perflock
:
:
:
perf_lock_rel(perf_lock_handle);

这个示例代码展示了如何动态加载 libqti-perfd-client.so 库并使用 perf_lock_acq 和 perf_lock_rel 函数来获取和释放性能锁。

Perflock 本地测试

Perflock 本地测试是一种工具,用于评估特定组合的 Perflock 操作码的有效性。
此工具位于 /usr/bin/ 目录下。
你可以将此工具作为一个用例来试验不同的 <资源, 操作码> 调优参数。一旦确认了所需的性能改进,可以将 Perflock 代码集成到你的软件中。
以下代码显示了语法:

perflock_native_test --acq <handle> <duration> <resource opcode, value, resource opcode, value,...>

以下是一些如何使用该工具的示例:
示例 1, 要为 Silver 集群获取 Perflock,并将最低频率设置为 1958400 KHz,持续 30 秒,运行以下命令:

perflock_native_test --acq 0 30000 0x44008100,1958400

示例 2, 要验证 Silver 集群的最低频率,运行以下命令:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq

示例 3, 要从 syslog 验证 Perflock 日志,运行以下命令:

cat /var/log/syslog

示例日志输出:

perflock_native_test: ANDR-PERFLOCK-TESTERANDR-PERFLOCK-TESTER: initialize() 60: NRP: lib name libqti-perfd-client.so
perflock_native_test: ANDR-PERFLOCK-TESTERANDR-PERFLOCK-TESTER: main() 502: NRP: resource_list[0] = 44008100 //银核最低频率操作码
perflock_native_test: ANDR-PERFLOCK-TESTERANDR-PERFLOCK-TESTER: main() 502: NRP: resource_list[1] = 7a6 // 银核最低频率十六进制值

Debug Perflock

以下是一些用于调试 Perflock 问题的日志机制示例:
示例 1, 要验证 PerfHAL 服务是否可用,运行以下命令:

ls /usr/bin | grep perf

示例 2, 要验证 PerfHAL 服务的运行状态,运行以下命令:

systemctl status perf-hal

示例 3,要在 /var/log/syslog 中启用 Perflock 日志和追踪,运行以下命令:

echo debug.trace.perf=1 >> /etc/build.prop
echo vendor.debug.trace.perf=1 >> /etc/build.prop
reboot

自定义内存

你可以使用 kswapd 管理虚拟内存,使用水印调节系统内存,并通过内存切割定义特定子系统的内存区域。

Kswapd

kswapd 是一个管理虚拟内存的内核线程。当系统内存不足时,kswapd 被激活,通过识别文件缓存中使用频率较低的页面并将其移动到交换空间(ZRAM)来回收内存。
kswapd 执行以下操作:

  • 监控系统的内存使用情况。
  • 在后台执行交换活动,以保持最佳的自由内存水平。

在这里插入图片描述

Watermark

watermark是在内存参数上设置的阈值或限制,有助于调节系统内存的分配和利用率。

参数描述
/proc/sys/vm/min_free_kbytes
  • 此参数确定系统必须在所有区域中保持的最小空闲内存量。
  • 它确保一定的内存储备可用于关键操作,例如处理需要立即分配内存的原子分配,这些操作不能等待内存回收。
  • 每个区域中保留的空闲页数量与其大小成比例。
/proc/sys/vm/watermark_scale_factor
  • 此因子控制 kswapd 的激进程度。
  • 它定义了 kswapd 被唤醒前系统中剩余的内存量,以及 kswapd 回到休眠状态前所需的空闲内存量。
  • 单位为 1/10,000。
  • 默认值为 10,这意味着水印之间的距离为节点或系统可用内存的 0.1%。最大值为 1000,即内存的 10%。
/proc/sys/vm/watermark_boost_factor
  • 此因子用于通过暂时为内存管理区域提供高水印来优化内存碎片化,这使得 kswapd 能够回收更多内存。
  • 单位为 1/10,000。
  • 默认值为 15,000,意味着在由于碎片化导致页块被混合的情况下,可以回收高达高水印 150% 的内存。
  • 回收水平由最近发生的碎片化事件的数量决定。提升因子为 0 表示禁用该功能。

有关更多信息,请参阅 内核文档

内存切割

内存切割指的是内核无法访问的特定内存区域,称为 no-map 区域。这些区域为特定子系统(如调制解调器、相机、aDSP、cDSP 和 TrustZone)专用,并且对 Linux 内核不可访问。
这些内存切割在源代码 arch/arm64/boot/dts/qcom/qcm6490.dtsi 文件中定义。
它们属于 reserved-memory 节点,可以配置。
以下代码显示了 cDSP、相机、调制解调器和 TrustZone 子系统的 no-map 区域:

reserved-memory {
 		cdsp_secure_heap_mem: cdsp-secure-heap@81800000 {
 			reg = <0x0 0x81800000 0x0 0x1e00000>;
 			no-map;
 		};
 
 		camera_mem: camera@84300000 {
 			reg = <0x0 0x84300000 0x0 0x500000>;
 			no-map;
 		};
 		adsp_mem: adsp@86100000 {
 			reg = <0x0 0x86100000 0x0 0x2800000>;
 			no-map;
 		};
 		cdsp_mem: cdsp@88900000 {
 			reg = <0x0 0x88900000 0x0 0x1e00000>;
 			no-map;
 		};
 		mpss_mem: mpss@8b800000 {
 			reg = <0x0 0x8b800000 0x0 0xf600000>;
 			no-map;
 		};
 
 		tz_stat_mem: tz-stat@c0000000 {
 			reg = <0x0 0xc0000000 0x0 0x100000>;
 			no-map;
 		};
 		tags_mem: tags@c0100000 {
 			reg = <0x0 0xc0100000 0x0 0x1200000>;
 			no-map;
 		};

你可以根据产品需求调整保留内存切割区域。这可能涉及删除调制解调器切割区域或减少 TrustZone 应用内存切割区域的大小。
例如,以下代码片段展示了如何禁用调制解调器内存切割以进行内存优化:

reserved-memory {
		mpss_mem: mpss@8b800000 {
 			reg = <0x0 0x8b800000 0x0 0xf600000>;
 			no-map;
                    status = "disabled";
 		};

在此代码中:

  • 0x8b800000 是调制解调器区域的基地址。
  • 0xf600000 是调制解调器区域的大小,即 246 MB。
  • 添加 status = “disabled” 使该区域可供 Linux 内核使用。

以下示例代码片段展示了如何将 TrustZone 受信任应用内存切割大小从 28 MB(0x1c00000)减少到 20 MB(0x1400000):

BeforeAfter
reserved memory {
trusted_apps_mem: trusted_apps@c1800000 {
reg = <0x0 0xc1800000 0x0 0x1c00000>;
no-map;
};
reserved memory {
trusted_apps_mem: trusted_apps@c1800000 {
reg = <0x0 0xc1800000 0x0 0x1400000>;
no-map;
};
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值