实时分析工具 rtla timerlat 介绍(一):交叉编译及使用

文摘   2024-12-02 18:43   陕西  

Corrector: TinyCorrect v0.2-rc2 - [spaces header]
Author:    王杰迅 wangjiexun@foxmail.com
Date:      2024/09/03
Revisor:   falcon falcon@tinylab.org
Project:   RISC-V Linux 内核剖析
Sponsor:   PLCT Lab, ISCAS

rtla timerlat 介绍(一):交叉编译及使用

前言

rtla timerlat 是一个 Linux 调度延迟测试及分析工具。

传统的 Linux 调度延迟测试工具(如 cyclictest)有一个局限性:只能测试出整体延迟,无法提供更详细的延迟分析,典型结果如下:

# cyclictest --mlockall --priority=97
policy: fifo: loadavg: 0.33 0.16 0.09 1/51 102
T: 0 (  102) P:97 I:1000 C:  10000 Min:    114 Act:  181 Avg:  185 Max:     417

而 rtla timerlat 可以将调度延迟划分为多个部分,便于开发者进行分析,找到造成较大延迟的原因,典型结果如下:

# rtla timerlat top -T 500 -s 500 -t -k -P f:95
  0 00:00:01   |          IRQ Timer Latency (us)        |         Thread Timer Latency (us)
CPU COUNT      |      cur       min       avg       max |      cur       min       avg       max
  0 #1015      |      236        37        42       236 |      594       213       227       594
---------------|----------------------------------------|---------------------------------------
ALL #1015   e0 |                 37        42       236 |                213       227       594
rtla timerlat hit stop tracing
## CPU 0 hit stop tracing, analyzing it ##
  IRQ handler delay:                                       157.68 us (26.52 %)
  IRQ latency:                                             236.24 us
  Timerlat IRQ duration:                                   242.08 us (40.72 %)
  Blocking thread:                                         101.84 us (17.13 %)
                            rtla:145                       101.84 us
    Blocking thread stack trace
                -> stack_trace_save
                -> timerlat_save_stack.constprop.0
                -> timerlat_irq
                -> trace_event_buffer_commit
                -> __hrtimer_run_queues.constprop.0
                -> hrtimer_interrupt
                -> riscv_timer_interrupt
                -> handle_percpu_devid_irq
                -> ring_buffer_map
                -> handle_irq_desc
                -> riscv_intc_irq
                -> handle_riscv_irq
------------------------------------------------------------------------
  Thread latency:                                          594.48 us (100%)

可以看到,除了提供整体延迟(Thread latency)外,rtla timerlat 还提供了各个阶段产生的延迟,后续我们会对各个延迟的具体含义进行解释及分析。

交叉编译

本文主要介绍 rtla 交叉编译的方法,在本地编译及运行的步骤基本一致,编译时不指定交叉编译器即可。

rtla 的源代码位于 Linux 内核源代码的 tools/tracing/rtla 目录下,其依赖于 libtracefs 和 libtraceevent,因此需要先交叉编译这两个库:

$ git clone git://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git
cd libtraceevent/
$ make CROSS_COMPILE=/path/to/cross/compile/riscv64-xx- CC=/path/to/cross/compile/riscv64-xx-gcc LD=/path/to/cross/compile/riscv64-xx-ld
$ sudo make install
cd ..
$ git clone git://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git
cd libtracefs/
$ make CROSS_COMPILE=/path/to/cross/compile/riscv64-xx- CC=/path/to/cross/compile/riscv64-xx-gcc LD=/path/to/cross/compile/riscv64-xx-ld

随后进入 rtla 源码目录下进行编译即可:

make CROSS_COMPILE=/path/to/cross/compile/riscv64-xx- CC=/path/to/cross/compile/riscv64-xx-gcc

编译完成后将其拷贝到开发板的根文件系统即可。

编译问题

在编译 rtla 前,Linux 源码首先会检查依赖的 libtracefs 和 libtraceevent 是否被成功安装。而在 6.11 之前的源码中,检测代码有微小 Bug,导致已经安装库后仍会检测不到,6.11-rc1 已进行了部分修复,可参见 commit1、commit2。

除此之外,还需修改 tools/build/features/test-libtraceevent.c 中的 #include <traceevent/trace-seq.h>#include <trace-seq.h>(类似 commit1)。

如果编译时报错未定义类型,如:

tracefs.h:55:7: error: unknown type name 'cpu_set_t'

可能是结构体的定义位于交叉编译器的库中,需要在 rtla 相应源码中添加:

#define _GNU_SOURCE

使用方法

内核配置

rtla timerlat 之所以能够获取更详细的延迟数据,是因为其不仅仅是一个应用程序,还使用了内核提供的 tracer 功能。因此需要使能内核的 timerlat tracer:

Kernel hacking  --->
  Tracers(FTRACE [=y])  --->
    Timerlat tracer(TIMERLAT_TRACER [=y])

常用参数

rtla timerlat 有两种模式:top 模式和 hist 模式。其中 top 模式记录测试过程中的最大延迟和函数调用栈,而 hist 模式则记录了测试过程中所有延迟的直方图。以下为常用的测试参数及其含义:

-p, --period us:设置延迟的测量周期(以 us 为单位)。

-i, --irq us:当 IRQ 延迟大于该设定值时将会停止测试。

-T, --thread us:当 Thread 延迟大于该设定值时将会停止测试。

-s, --stack us:当 Thread 延迟大于该设定值时将会保存函数调用栈。

-t, --trace [file]:保存测试结果到指定文件(默认为当前目录下的 timerlat_trace.txt)。

-q, --quiet:仅在测试结束后输出总结数据。

-d, --duration time[s|m|h|d]:设置测试过程的持续时间。

-P, --priority o:prio|r:prio|f:prio|d:runtime:period:设置测试线程的调度参数,例如 -P f:95 代表使用 SCHED_FIFO 调度策略且优先级为 95。o 代表 SCHED_OTHER,r 代表使用 SCHED_RR,f 代表使用 SCHED_FIFO。

更详尽的介绍可自行查阅 rtla timerlat 文档。

使用案例

一个典型命令为 rtla timerlat top -T 500 -s 500 -t -k -P f:95,该命令使用设置测试线程调度策略为 SCHED_FIFO,并且优先级为 95,当 Thread 延迟大于 500us 时将会停止测试,并打印函数调用栈。

  0 00:00:01   |          IRQ Timer Latency (us)        |         Thread Timer Latency (us)
CPU COUNT      |      cur       min       avg       max |      cur       min       avg       max
  0 #1015      |      236        37        42       236 |      594       213       227       594
---------------|----------------------------------------|---------------------------------------
ALL #1015   e0 |                 37        42       236 |                213       227       594
rtla timerlat hit stop tracing
## CPU 0 hit stop tracing, analyzing it ##
  IRQ handler delay:                                       157.68 us (26.52 %)
  IRQ latency:                                             236.24 us
  Timerlat IRQ duration:                                   242.08 us (40.72 %)
  Blocking thread:                                         101.84 us (17.13 %)
                            rtla:145                       101.84 us
    Blocking thread stack trace
                -> stack_trace_save
                -> timerlat_save_stack.constprop.0
                -> timerlat_irq
                -> trace_event_buffer_commit
                -> __hrtimer_run_queues.constprop.0
                -> hrtimer_interrupt
                -> riscv_timer_interrupt
                -> handle_percpu_devid_irq
                -> ring_buffer_map
                -> handle_irq_desc
                -> riscv_intc_irq
                -> handle_riscv_irq
------------------------------------------------------------------------
  Thread latency:                                          594.48 us (100%)

上面是在某单核 RISC-V 开发板上的执行结果,由测试数据和延迟分析两部分构成。

测试数据以表格形式出现,由于该开发板仅有单核,因此只有一行数据。对于多核开发板,每个 CPU 都有一行测试数据。测试的延迟数据分为 IRQ Timer Latency 和 Thread Timer Latency 两类,IRQ Timer Latency 代表进入定时器中断处理程序的延迟,Thread Timer Latency 代表进入测试线程的延迟,后者在数值上包含前者。cur、min、avg、max 分别代表测试数据中的当前值、最小值、平均值、最大值。

延迟分析提供了更细化的各阶段延迟,并打印出了可能造成阻塞的线程名称和函数调用栈,便于开发者进行延迟分析。

总结

本文介绍了 rtla timerlat 的基本功能、编译过程和使用方法,后续文章将介绍其原理及各个延迟的具体含义。

参考资料

  • tools: build: use correct lib name for libtracefs feature detection
  • tools: Make pkg-config dependency checks usable by other tools
  • rtla timerlat 文档
  • Linux scheduling latency debug and analysis

首发地址:https://tinylab.org/linux-rtla-1
技术服务:https://tinylab.org/ruma.tech

Linux内核之旅
Linux内核之旅
 最新文章