优化工具

可用的优化工具通过不同构建系统目标分析 占用空间与内存使用 和 数据结构。还可生成 HTML 仪表盘,以更灵活的交互方式查看构建产物和指标。

占用空间与内存使用

构建系统提供 3 个目标,用于查看和分析生成镜像中的 RAM、ROM 和栈使用情况。这些工具针对最终镜像运行,提供 RAM 和 ROM 中符号大小及代码占用信息。此外,还可借助编译器功能生成最坏情况下的栈使用分析。

本节介绍的某些工具根据符号的物理组织方式排列输出。部分符号可能位于项目目录树之外,或缺少按名称显示所需的元数据,因此使用以下顶层容器对它们分组:

  • Hidden:RAM 和 ROM 报告将所有找不到匹配映射文件的待处理符号列入 Hidden 类别。

    这表示对应符号的文件未加入元数据文件、为空或未定义。工具既无法获取该符号的函数名称,也无法识别其来源。

  • No paths:RAM 和 ROM 报告将所有带相对路径的待处理符号列入 No paths 类别。

    这表示无法根据绝对路径,将所列符号归入报告树结构中的某个具体文件。工具能获取函数名称,但无法识别其来源。

    备注

    同一函数可能出现多次,No paths 类别会将它们合并为一个条目,列出总占用。

构建目标:ram_report

以表格形式列出所有已编译对象及其 RAM 占用,包括每个符号的字节数和占比。数据按对象在目录树中的文件系统位置及包含符号的文件分组。

针对所用开发板使用 ram_report 目标,如下例所示。如果使用 Sysbuild (System build),请参见 Dedicated image build targets。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t ram_report

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild ram_report

这些命令生成的输出类似于:

Path                                                           Size    %      Address
========================================================================================
Root                                                           4637 100.00%  -
├── (hidden)                                                      4   0.09%  -
├── (no paths)                                                 2748  59.26%  -
│   ├── _cpus_active                                              4   0.09%  0x20000314
│   ├── _kernel                                                  32   0.69%  0x20000318
│   ├── _sw_isr_table                                           384   8.28%  0x00006474
│   ├── cli.1                                                    16   0.35%  0x20000254
│   ├── on.2                                                      4   0.09%  0x20000264
│   ├── poll_out_lock.0                                           4   0.09%  0x200002d4
│   ├── z_idle_threads                                          128   2.76%  0x20000120
│   ├── z_interrupt_stacks                                     2048  44.17%  0x20000360
│   └── z_main_thread                                           128   2.76%  0x200001a0
├── WORKSPACE                                                   184   3.97%  -
│   └── modules                                                 184   3.97%  -
│       └── hal                                                 184   3.97%  -
│           └── nordic                                          184   3.97%  -
│               └── nrfx                                        184   3.97%  -
│                   └── drivers                                 184   3.97%  -
│                       └── src                                 184   3.97%  -
│                           ├── nrfx_clock.c                      8   0.17%  -
│                           │   └── m_clock_cb                    8   0.17%  0x200002e4
│                           ├── nrfx_gpiote.c                   132   2.85%  -
│                           │   └── m_cb                        132   2.85%  0x20000060
│                           ├── nrfx_ppi.c                        4   0.09%  -
│                           │   └── m_channels_allocated          4   0.09%  0x200000e4
│                           └── nrfx_twim.c                      40   0.86%  -
│                               └── m_cb                         40   0.86%  0x200002ec
└── ZEPHYR_BASE                                                1701  36.68%  -
    ├── arch                                                      5   0.11%  -
    │   └── arm                                                   5   0.11%  -
    │       └── core                                              5   0.11%  -
    │           ├── mpu                                           1   0.02%  -
    │           │   └── arm_mpu.c                                 1   0.02%  -
    │           │       └── static_regions_num                    1   0.02%  0x20000348
    │           └── tls.c                                         4   0.09%  -
    │               └── z_arm_tls_ptr                             4   0.09%  0x20000240
    ├── drivers                                                 258   5.56%  -
    │   ├── ...                                                 ...    ...%
========================================================================================
                                                               4637

构建目标:rom_report

以表格形式列出所有已编译对象及其 ROM 占用,包括每个符号的字节数和占比。数据按对象在目录树中的文件系统位置及包含符号的文件分组。

针对所用开发板使用 rom_report 目标,如下例所示。如果使用 Sysbuild (System build),请参见 Dedicated image build targets。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t rom_report

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild rom_report

这些命令生成的输出类似于:

Path                                                           Size    %      Address
========================================================================================
Root                                                          27828 100.00%  -
├── ...                                                         ...    ...%
└── ZEPHYR_BASE                                               13558  48.72%  -
    ├── arch                                                   1766   6.35%  -
    │   └── arm                                                1766   6.35%  -
    │       └── core                                           1766   6.35%  -
    │           ├── cortex_m                                   1020   3.67%  -
    │           │   ├── fault.c                                 620   2.23%  -
    │           │   │   ├── bus_fault.constprop.0               108   0.39%  0x00000749
    │           │   │   ├── mem_manage_fault.constprop.0        120   0.43%  0x000007b5
    │           │   │   ├── usage_fault.constprop.0              84   0.30%  0x000006f5
    │           │   │   ├── z_arm_fault                         292   1.05%  0x0000082d
    │           │   │   └── z_arm_fault_init                     16   0.06%  0x00000951
    │           │   ├── ...                                     ...    ...%
    ├── boards                                                   32   0.11%  -
    │   └── arm                                                  32   0.11%  -
    │       └── reel_board                                       32   0.11%  -
    │           └── board.c                                      32   0.11%  -
    │               ├── __init_board_reel_board_init              8   0.03%  0x000063e4
    │               └── board_reel_board_init                    24   0.09%  0x00000ed5
    ├── build                                                   194   0.70%  -
    │   └── zephyr                                              194   0.70%  -
    │       ├── isr_tables.c                                    192   0.69%  -
    │       │   └── _irq_vector_table                           192   0.69%  0x00000040
    │       └── misc                                              2   0.01%  -
    │           └── generated                                     2   0.01%  -
    │               └── configs.c                                 2   0.01%  -
    │                   └── _ConfigAbsSyms                        2   0.01%  0x00005945
    ├── drivers                                                6282  22.57%  -
    │   ├── ...                                                 ...    ...%
========================================================================================
                                                              21652

构建目标:ram_plot/rom_plot

与 ram_report 和 rom_report 构建目标类似,这些目标以旭日图生成可视化内存使用报告。用户可单击扇区浏览目录结构,将鼠标悬停在扇区上查看详细信息。

运行这些目标会先生成命令行报告,再打开浏览器窗口。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t ram_plot

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild ram_plot
RAM 使用情况旭日图

ROM 使用情况同理。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t rom_plot

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild rom_plot
ROM 使用情况旭日图

构建目标:puncover

此目标使用名为 puncover 的第三方工具,地址为 https://github.com/HBehrens/puncover。构建该目标会启动本地 Web 服务器,供你通过浏览器查看文件及其 ROM、RAM 和栈占用。

使用此目标之前,安装 puncover Python 模块:

pip3 install --user puncover

警告

这是第三方工具,其可用性可能随时变化。请查看 GitHub 问题,并向项目维护者报告新问题。

安装 Python 模块后,针对所用开发板使用 puncover 目标,如下例所示。如果使用 Sysbuild (System build),请参见 Dedicated image build targets。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t puncover

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild puncover

puncover 目标默认在 localhost:5000 启动本地 Web 服务器。可通过环境变量 PUNCOVER_HOST 和 PUNCOVER_PORT 更改 HTTP 服务器的主机 IP 和端口。在 EXTRA_PUNCOVER_ARGS 中可定义并传入其他 puncover 参数。

要在交互式 Web 应用中查看最坏情况下的栈使用分析,构建时启用 CONFIG_STACK_USAGE。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world -- -DCONFIG_STACK_USAGE=y -DCONFIG_CALLGRAPH_INFO=y
west build -t puncover

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board -DCONFIG_STACK_USAGE=y -DCONFIG_CALLGRAPH_INFO=y samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild puncover

如果希望将发现的最坏栈使用情况输出为 JSON 报告而不启动 Web 应用,可添加 --generate-report --non-interactive --report-type json 选项进行非交互式使用。为每个关注的函数添加 --report-max-static-stack-usage FUNCTION_NAME:::MAXIMAL_STACK_SIZE 形式的参数,即可将其纳入报告。例如,导出 log_process_thread_func、shell_thread、bg_thread_main 和 work_queue_main 的命令如下:

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world -- -DCONFIG_STACK_USAGE=y -DCONFIG_CALLGRAPH_INFO=y -DEXTRA_PUNCOVER_ARGS="--generate-report;--non-interactive;--report-type;json;--report-max-static-stack-usage;log_process_thread_func:::832;--report-max-static-stack-usage;shell_thread:::4160;--report-max-static-stack-usage;bg_thread_main:::2112;--report-max-static-stack-usage;work_queue_main:::1088;--report-filename;$PWD/report"
west build -t puncover

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board -DCONFIG_STACK_USAGE=y -DCONFIG_CALLGRAPH_INFO=y -DEXTRA_PUNCOVER_ARGS="--generate-report;--non-interactive;--report-type;json;--report-max-static-stack-usage;log_process_thread_func:::832;--report-max-static-stack-usage;shell_thread:::4160;--report-max-static-stack-usage;bg_thread_main:::2112;--report-max-static-stack-usage;work_queue_main:::1088;--report-filename;$PWD/report" samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild puncover

也可将所有参数放入 YAML 配置,便于维护和整体查看:

elf_file: ~/zephyrproject/zephyr/samples/net/mqtt_publisher/build/zephyr/zephyr.elf
gcc-tools-base: ~/zephyr-sdk-1.0.1/gnu/arm-zephyr-eabi/bin/arm-zephyr-eabi-
src_root: ~/zephyrproject/zephyr
build_dir: ~/zephyrproject/zephyr/samples/net/mqtt_publisher/build
generate-report: true
non-interactive: true
report-type: json
report-max-static-stack-usage:
   - log_process_thread_func:::832
   - shell_thread:::4160
   - bg_thread_main:::2112
   - work_queue_main:::1088
   - mgmt_event_work_handler:::896

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world -- -DCONFIG_STACK_USAGE=y -DCONFIG_CALLGRAPH_INFO=y -DEXTRA_PUNCOVER_ARGS="-c puncover_config.yaml"
west build -t puncover

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board -DCONFIG_STACK_USAGE=y -DCONFIG_CALLGRAPH_INFO=y -DEXTRA_PUNCOVER_ARGS="-c puncover_config.yaml" samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild puncover

数据结构

构建目标:pahole

Poke-a-hole(pahole)是对象文件分析工具,用于查看数据结构大小,以及编译器将数据元素按 CPU 字长对齐时产生的空洞。

使用此目标前必须安装 Poke-a-hole(pahole)。可从 https://git.kernel.org/pub/scm/devel/pahole/pahole.git 获取;Fedora 和 Ubuntu 的 dwarves 软件包也提供此工具:

sudo apt-get install dwarves

也可以从 Fedora 获取:

sudo dnf install dwarves

安装软件包后,针对所用开发板使用 pahole 目标,如下例所示。如果使用 Sysbuild (System build),请参见 Dedicated image build targets。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t pahole

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild pahole

Pahole 会在控制台生成类似以下内容的输出:

/* Used at: [...]/build/zephyr/kobject_hash.c */
/* <375> [...]/zephyr/include/zephyr/sys/dlist.h:37 */
union {
        struct _dnode *            head;               /*     0     4 */
        struct _dnode *            next;               /*     0     4 */
};
/* Used at: [...]/build/zephyr/kobject_hash.c */
/* <397> [...]/zephyr/include/zephyr/sys/dlist.h:36 */
struct _dnode {
        union {
                struct _dnode *    head;                 /*     0     4 */
                struct _dnode *    next;                 /*     0     4 */
        };                                               /*     0     4 */
        union {
                struct _dnode *    tail;                 /*     4     4 */
                struct _dnode *    prev;                 /*     4     4 */
        };                                               /*     4     4 */

        /* size: 8, cachelines: 1, members: 2 */
        /* last cacheline: 8 bytes */
};
/* Used at: [...]/build/zephyr/kobject_hash.c */
/* <3b7> [...]/zephyr/include/zephyr/sys/dlist.h:41 */
union {
        struct _dnode *            tail;               /*     0     4 */
        struct _dnode *            prev;               /*     0     4 */
};
...
...

仪表盘

可以生成 HTML 仪表盘,将各种工具的输出和产物汇集到一个简洁视图中。除构建结果的基本摘要外,还包含以下信息:

  • 完整内存报告(RAM、ROM),提供可逐层展开的表格及 图表,对应 footprint、ram_plot 和 rom_plot 构建目标。

  • Kconfig 符号值及其来源,对应 traceconfig 构建目标。

  • 初始化级别及函数名,以及系统初始化相对于设备树的优先级问题报告,对应 initlevels 构建目标。

  • 可浏览的设备树视图,包含属性值及绑定中的详细信息。

针对所用开发板使用 dashboard 目标,如下例所示。如果使用 Sysbuild (System build),请参见 Dedicated image build targets。

Using west:

# From the root of the zephyr repository
west build -b reel_board samples/hello_world
west build -t dashboard

Using CMake and ninja:

# From the root of the zephyr repository
# Use cmake to configure a Ninja-based buildsystem:
cmake -Bbuild -GNinja -DBOARD=reel_board samples/hello_world

# Now run the build tool on the generated build system:
ninja -Cbuild dashboard

这会生成以下输出文件,并在默认浏览器中打开:

build/dashboard/index.html
Dashboard