> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 针对性能调优进行定制

定制是一个包括对系统各方面进行微调的过程，可以显著影响系统的整体性能和功耗。

可以对 CPU 调度器、CPU 频率调节器（governor）、动态电压和频率调节（DVFS）调节器、用户空间资源管理器（URM）以及内存进行微调。建议在通过大量的性能和功耗分析获得深入了解之后再进行任何调优。

<Warning>
  任何定制都可能影响设备的功耗和性能。因此，在执行任何定制之前，务必在所有相关用例中验证其影响。
</Warning>

## **定制 CPU 调度器**

您可以定制 CPU 调度器的功能，例如利用率钳制（UCLAMP 或 util clamp）调度器。

更多信息请参见[了解 CPU 调度器](./features-impacting-performance#understand-the-cpu-scheduler)。

### **UCLAMP**

UCLAMP 是一项调度器功能，允许用户空间管理任务的性能需求。

它是一种提示机制，帮助调度器了解任务的性能需求和限制，从而协助调度器做出明智的决策。

当使用 `schedutil` CPU 频率调节器时，UCLAMP 决定 CPU 频率的选择。UCLAMP 值的范围为 0 到 1024。

可以为 UCLAMP 定制以下参数：

* `sched_util_clamp_min`：此参数为单个任务和任务组设置最低可接受的性能水平，确保任务即使在低需求时期也能获得足够的资源来运行。任务请求的任何 `uclamp.min` 值都不能超过 `sched_util_clamp_min`。
  * 对于调度器，它充当跟踪任务使用情况的按实体负载跟踪（PELT）信号的下限。
  * 对于 CPU 频率，它指示调节器选择能够满足任务性能需求的频率，从而确保响应性和效率。Qualcomm 调优值为 1024。要设置此参数，请在设备上运行以下命令：
  ```text theme={null}
  echo 1024 > /proc/sys/kernel/sched_util_clamp_min
  ```
* `sched_util_clamp_max`：此参数为单个任务和任务组设置最高可接受的性能水平。它确保任务不会消耗过多资源，从而防止资源争用和系统不稳定。任务请求的任何 `uclamp.max` 值都不能超过 `sched_util_clamp_max`。
  * 对于调度器，它充当跟踪任务使用情况的 PELT 信号的上限。
  * 对于 CPU 频率，如果任务需求超过可用频率，调节器可能会调整频率以防止功耗过高。Qualcomm 调优值为 1024。要设置此参数，请在设备上运行以下命令：
  ```text theme={null}
  echo 1024 > /proc/sys/kernel/sched_util_clamp_max
  ```
* `sched_util_clamp_min_rt_default`：默认情况下，实时（RT）任务始终以最高频率和最高 CPU 能力运行。此参数允许您在使用 UCLAMP 时更改 RT 任务的默认行为。它允许为 RT 任务调优最佳值，在不将其推至最大性能点的情况下提供良好的性能。这种行为可以满足系统需求，而无需一直消耗功率并运行在最大性能点。Qualcomm 调优值为 128。要设置此参数，请在设备上运行以下命令：
  ```text theme={null}
  echo 128 > /proc/sys/kernel/sched_util_clamp_min_rt_default
  ```

更多信息请参见 [Utilization Clamping](https://docs.kernel.org/scheduler/sched-util-clamp.html)。

## **定制 CPU 频率调节器**

您可以使用 `scaling_governor` 节点配置 CPU 频率调节器以增强 CPU 性能。

<Note>
  包含 `policy7` 的命令在 QCS5430 FP1 上不受支持。
</Note>

要为 Qualcomm Dragonwing<sup>™</sup> IQ-9075 和 Qualcomm Dragonwing<sup>™</sup> IQ-8275 定制频率调节器，请参见相应的附录。以下指南面向具有授权访问权限的许可用户：

* [Qualcomm Linux Performance Guide - Addendum for Qualcomm Dragonwing IQ-9075](https://docs.qualcomm.com/bundle/resource/topics/80-80023-10A/overview.html)
* [Qualcomm Linux Performance Guide - Addendum for Qualcomm Dragonwing IQ-8275](https://docs.qualcomm.com/bundle/resource/topics/80-80023-10B/overview.html)

<Note>
  下表中指定的命令应在设备上运行。
</Note>

**表：为 QCS6490、QCS5430 FP2、FP2.5、FP3 定制 CPU 频率调节器的命令**

| 命令                                                                                                                                                                                                                                                  | 用途                                                                                                                                   |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor`<br />`echo performance > /sys/devices/system/cpu/cpufreq/policy4/scaling_governor`<br />`echo performance > /sys/devices/system/cpu/cpufreq/policy7/scaling_governor` | 设置 CPU 调节器以增强系统性能。                                                                                                                   |
| `cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor`<br />`cat /sys/devices/system/cpu/cpufreq/policy4/scaling_governor`<br />`cat /sys/devices/system/cpu/cpufreq/policy7/scaling_governor`                                              | 验证 CPU 频率调节器。                                                                                                                        |
| `echo schedutil > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor`<br />`echo schedutil > /sys/devices/system/cpu/cpufreq/policy4/scaling_governor`<br />`echo schedutil > /sys/devices/system/cpu/cpufreq/policy7/scaling_governor`       | 将 CPU 频率调节器设置为 `schedutil`。                                                                                                          |
| `echo 1000 > /sys/devices/system/cpu/cpufreq/policyX/schedutil/rate_limit_us`                                                                                                                                                                       | 定制 `rate_limit_us`。`policyX` 中 `X` 的值对应集群 0、4 和 7。这是 `schedutil` 调节器参数。其值以微秒为单位。调节器会等待 `rate_limit_us` 时间以重新评估负载。Qualcomm 调优值为 1000。 |

<Note>
  下表中指定的命令应在设备上运行。
</Note>

**表：为 Dragonwing IQ-615 定制 CPU 频率调节器的命令**

| 命令                                                                                                                                                               | 用途                                                                                                                                         |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor`<br />`echo performance > /sys/devices/system/cpu/cpufreq/policy6/scaling_governor` | 设置 CPU 调节器以增强系统性能。                                                                                                                         |
| `cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor`<br />`cat /sys/devices/system/cpu/cpufreq/policy6/scaling_governor`                               | 验证 CPU 频率调节器。                                                                                                                              |
| `echo schedutil > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor`<br />`echo schedutil > /sys/devices/system/cpu/cpufreq/policy6/scaling_governor`     | 将 CPU 频率调节器设置为 `schedutil`。                                                                                                                |
| `echo 1000 > /sys/devices/system/cpu/cpufreq/policyX/schedutil/rate_limit_us`                                                                                    | 定制 `rate_limit_us`。`policyX` 中 `X` 的值对应集群 0 和 6。这是 `schedutil` 调节器参数。其值以微秒为单位。调节器在上次评估负载后会等待 `rate_limit_us` 时间以重新评估负载。Qualcomm 调优值为 1000。 |

## **定制 DVFS 调节器**

您可以根据设备的功耗和性能需求，使用 DTSI 文件定制静态映射 DVFS 调节器和带宽监控（BWMON）调节器。

### **定制静态映射 DVFS 调节器**

您可以根据功耗和性能需求，在源代码的 `arch/arm64/boot/dts/qcom/<target>.dtsi` 文件中定制 CPU 频率与 L3/DDR 频率之间的映射。

在 DTSI 文件中，每个 CPU 节点都有一个 `operating-points-v2 = <&cpux_opp_table>` 条目，其中 `cpux_opp_table` 保存了 CPU 频率与 L3 及 DDR 频率之间的静态映射。

例如，以下条目表示 CPU 0 频率运行在 300 MHz：

```text theme={null}
cpu0_opp_300mhz: opp-300000000 {
                opp-hz = /bits/ 64 <300000000>;
                pp-peak-kBps = <800000 9600000>;
                };
```

当 CPU 0 运行在 300 MHz 时，它会执行以下操作：

* 向 L3 投票 9600000，即 9600000/w（其中 w = 32）= 300,000，对应 300 MHz
* 向 DDR 投票 800000，即 800000/w（其中 w = 4）= 200,00，对应 200 MHz

在此示例中，'w' 表示单个周期内可写入的字节数。

* 对于 L3，该值为 32，即每个周期一次事务，每次事务 32 字节。
* 对于双通道 DDR，该值为 4。每个通道每个周期可执行两次事务（因为它是 DDR 内存），每次事务为 2 字节。

更多信息请参见 [Generic OPP (Operating Performance Points) Bindings](https://www.kernel.org/doc/Documentation/devicetree/bindings/opp/opp.txt)。

这些表指定的是每通道 DDR 值。这意味着映射是在 CPU 频率与每个内存控制器通道的带宽之间进行的。

<Warning>
  如果更改 DTSI 文件，将影响设备的功耗和性能。在更改任何节点之前，请确保在所有相关用例中验证其影响。
</Warning>

### **定制 BWMON 调节器**

您可以根据功耗和性能需求，在源代码的 `arch/arm64/boot/dts/qcom/<target>.dtsi` 文件中，为末级缓存控制器（LLCC）和 DDR 投票定制 `bwmon_opp_table`。

以下代码示例包含 DDR 频率级别和 LLCC 频率级别，每个级别都会根据流量转换为对 LLCC 和 DDR 的投票。

以下 DTSI 条目根据 LLCC 到 DDR 之间的 CPU 流量向 DDR 投票，对应 200 MHz。在此示例中，800000/w（其中 w = 4）等于 200000：

```text theme={null}
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）等于 150000：

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

在这些示例中，'w' 表示单个周期内可写入的字节数。

* 对于 DDR，该值为 4。每个通道每个周期可执行两次事务（DDR 内存），每次事务为 2 字节。
* 对于 LLCC，该值为 16。

## **使用扩展定制 URM**

URM 扩展承载 Qualcomm 芯片组特定的配置和用例特定的定制。这些扩展支持在运行时集成额外的配置和扩展模块，从而在不修改核心 URM 实现的情况下实现灵活的调优和策略定制。

### **定制按应用调优**

针对 Qualcomm 特定芯片组的按应用调优定义在 `userspace-resource-manager-extensions/Configs/PerApp.yaml` 中。

以下示例代码展示了针对 GST 和 cyclic test 应用的按应用调优用法：

```text theme={null}
PerAppConfigs:
- App: "gst-launch-"
   Threads:
      - {"cam-server": "FOCUSED_CGROUP_IDENTIFIER"}
      - {"gst-launch-": "FOCUSED_CGROUP_IDENTIFIER"}

- App: "cyclictest"
   Threads:
      - {"cyclictest": "FOCUSED_CGROUP_IDENTIFIER"}
   Configurations: ["0x00800001"]
```

芯片组特定的调优配置定义在 `userspace-resource-manager-extensions/Configs/<target-specific>` 中。

### **定制信号设置**

针对 Qualcomm 特定芯片组的信号配置定义在 `userspace-resource-manager-extensions/Configs/SignalsConfig.yaml` 配置文件中。

以下示例代码展示了应用启动时信号设置的用法：

```text theme={null}
SignalConfigs:
- SigId: "0x0001"
   Category: "0x01"
   Name: URM_APP_OPEN
   Enable: true
   Permissions: ["system", "third_party"]
   Resources:
      - {ResCode: "RES_CGRP_RUN_CORES", Values: [2, 0,1,2,3]}
      - {ResCode: "RES_CGRP_CPU_LATENCY", Values: [4, -20]}

- SigId: "0x0001"
   Category: "0x80"
   Name: RT_TRIGGER
   Enable: true
   Permissions: ["system", "third_party"]
   Resources:
      - {ResCode: "0x00800000", Values: [0]}
      - {ResCode: "0x00800001", Values: [0]}
      - {ResCode: "0x00800002", Values: [0]}
      - {ResCode: "0x00030003", Values: [-1]}
      - {ResCode: "0x00040003", ResInfo: "0x00000000", Values: [1]}
      - {ResCode: "0x00040004", ResInfo: "0x00000100", Values: [1]}
      - {ResCode: "0x00040005", ResInfo: "0x00000200", Values: [1]}
```

芯片组特定的 `SignalsConfig.yaml` 文件位于 `userspace-resource-manager-extensions/Configs/<target-specific>` 下，会覆盖通用的信号调优。

### **定制资源配置**

针对通用 Qualcomm 特定芯片组的资源配置定义在 `userspace-resource-manager-extensions/Configs/ResourcesConfig.yaml` 中。

以下示例代码展示了资源配置的定制：

```text theme={null}
ResourceConfigs:
- ResType: "0x05"
   ResID: "0x0003"
   Name: "RES_KGSL_DEF_PWRLEVEL"
   Path: "/sys/class/kgsl/kgsl-3d0/default_pwrlevel"
   Supported: true
   LowThreshold: 0
   Permissions: "third_party"
   Modes: ["display_on", "doze"]
   Policy: "lower_is_better"
   ApplyType: "global"

- ResType: "0x05"
   ResID: "0x0004"
   Name: "RES_KGSL_DEVFREQ_MAX"
   Path: "/sys/class/kgsl/kgsl-3d0/devfreq/max_freq"
   Supported: true
   Permissions: "third_party"
   Modes: ["display_on", "doze"]
   Policy: "lower_is_better"
   ApplyType: "global"
```

芯片组特定的 `ResourcesConfig.yaml` 文件位于 `userspace-resource-manager-extensions/Configs/<target-specific>` 下，会覆盖通用的资源配置。

### **定制初始化配置**

针对所有通用 Qualcomm 特定芯片组的初始化配置定义在 `userspace-resource-manager-extensions/Configs/InitConfig.yaml` 中。

以下示例展示了如何定制初始化配置：

```text theme={null}
InitConfigs:
- IRQConfigs:
   - AffineIRQToCluster: [-1, 0]
```

芯片组特定的 `InitConfig.yaml` 文件位于 `e-manager-extensions/Configs/<target-specific>` 下。

### **使用自定义插件和资源扩展 URM**

URM 提供了一个扩展框架，支持集成自定义资源和插件，以满足平台或用例特定的需求。

例如，以下代码段注册了自定义资源，如 `0x00800000`（调节器更改资源）和 `0x00800002`（工作队列亲和性资源）。它还实现了一个扩展，用于优化 cyclictest 应用的信号处理。

```text theme={null}
URM_REGISTER_RES_APPLIER_CB(0x00800000, governorApplierCallback)
URM_REGISTER_RES_APPLIER_CB(0x00800002, workqueueApplierCallback)
URM_REGISTER_RES_TEAR_CB(0x00800000, governorTearCallback)

static void postProcessCallback(void* context) {
   if(context == nullptr) {
      return;
   }

   PostProcessCBData* cbData = static_cast<PostProcessCBData*>(context);
   if(cbData == nullptr) {
      return;
   }

   // Match to our usecase
   cbData->mSigId = CONSTRUCT_SIG_CODE(0x80, 0x0001);
   cbData->mSigType = DEFAULT_SIGNAL_TYPE;
}

URM_REGISTER_POST_PROCESS_CB("cyclictest", postProcessCallback)
```

有关扩展和定制的更多信息，请参见 [Userspace Resource Manager Extensions](https://github.com/qualcomm/userspace-resource-manager-extensions/blob/main/docs/README.md/)。

## **定制内存**

您可以使用 Kswapd 管理虚拟内存，使用水位线（watermark）调节系统内存，并通过内存 carveout 为特定子系统定义内存区域。

### **Kswapd**

Kswapd 是管理虚拟内存的内核线程。当系统空闲内存不足时，Kswapd 会被激活，通过从文件缓存中识别使用频率较低的页并将其移动到交换空间（ZRAM）来回收内存。

Kswapd 执行以下操作：

* 监控系统的内存使用情况
* 在后台执行交换活动，以维持最佳的空闲内存水平

<div className="flex flex-col items-center gap-2">
  <img src="https://mintcdn.com/qualcomm-prod/rpHTx_a6zriKQll9/System/Performance/media/k2l-performance/cpu_usage_performance_using_kswapd.png?fit=max&auto=format&n=rpHTx_a6zriKQll9&q=85&s=e547c0a400b7af1265a380086444a776" alt="图：使用 Kswapd 时的 CPU 使用率与性能对比" width="687" height="460" data-path="System/Performance/media/k2l-performance/cpu_usage_performance_using_kswapd.png" />

  <p className="text-sm text-gray-700">
    图：使用 Kswapd 时的 CPU 使用率与性能对比
  </p>
</div>

### **水位线（Watermark）**

水位线是设置在内存参数上的阈值或限制，有助于调节系统内存的分配和使用。

**表：水位线参数**

|                 **参数**                |                                                                                              **说明**                                                                                              |
| :-----------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|     `/proc/sys/vm/min_free_kbytes`    |                                  <ul><li>此参数确定系统必须在所有 zone 中保持的最小空闲内存量。</li><li>它确保为关键操作保留一定的内存储备，例如处理无法等待内存回收的原子分配。</li><li>每个 zone 中保留的空闲页数量与其大小成正比。</li></ul>                                 |
| `/proc/sys/vm/watermark_scale_factor` |           <ul><li>此因子控制 Kswapd 的积极程度。</li><li>它定义了唤醒 Kswapd 之前系统剩余的内存量，以及 Kswapd 恢复休眠所需的空闲内存量。</li><li>单位为万分之几。</li><li>默认值 10 表示水位线之间的距离为节点或系统可用内存的 0.1%。最大值为 1000，即内存的 10%。</li></ul>          |
| `/proc/sys/vm/watermark_boost_factor` | <ul><li>此因子用于通过临时为内存管理区域提供高水位线来优化内存碎片，从而允许 Kswapd 回收更多内存。</li><li>单位为万分之几。</li><li>默认值 15,000 表示当页块（pageblock）因碎片化而混合时，最多回收高水位线的 150%。</li><li>近期发生的碎片化事件数量决定了回收级别。boost 因子为 0 时禁用此功能。</li></ul> |

更多信息请参见 [Documentation for /proc/sys/vm/](https://www.kernel.org/doc/Documentation/admin-guide/sysctl/vm.rst)。

### **内存 carveout**

内存 carveout 是指内核无法寻址的特定内存区域，称为 no-map 区域。调制解调器、摄像头、aDSP、cDSP 以及 Qualcomm<sup>®</sup> 可信执行环境（TEE）/TrustZone（TZ）等特定子系统独占使用这些区域，因此 Linux 内核无法访问它们。

这些 carveout 定义在源代码的 `arch/arm64/boot/dts/qcom/<target>.dtsi` 中。

它们属于 `reserved-memory` 节点，并且可以进行配置。

以下代码展示了 cDSP、摄像头、调制解调器和 QTEE/TrustZone（TZ）子系统的 no-map 区域：

```text theme={null}
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;
        };
```

您可以根据产品需求调整保留内存 carveout 区域。这种调整可以包括移除调制解调器 carveout 区域，或减小 QTEE/TrustZone（TZ）应用内存 carveout 区域的大小。

例如，以下代码片段展示了如何禁用调制解调器内存 carveout 以优化内存：

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

在此代码中：

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

以下示例代码片段展示了如何将 QTEE/TrustZone（TZ）应用的内存 carveout 大小从 28 MB（`0x1c00000`）减小到 20 MB（`0x1400000`）：

**修改前：**

```text theme={null}
reserved-memory {
    trusted_apps_mem: trusted_apps@c1800000 {
        reg = <0x0 0xc1800000 0x0 0x1c00000>;
        no-map;
    };
```

**修改后：**

```text theme={null}
reserved-memory {
    trusted_apps_mem: trusted_apps@c1800000 {
        reg = <0x0 0xc1800000 0x0 0x1400000>;
        no-map;
    };
```

## **后续步骤**

* [排查性能问题](./troubleshoot-performance-issues)
