泰晓科技 -- 聚焦 Linux - 追本溯源,见微知著!
网站地址:https://tinylab.org

泰晓Linux知识星球:1300+知识点,520+用户
请稍侯

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

王杰迅 创作于 2024/11/04

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

1 前言

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

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

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

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

  1. # rtla timerlat top -T 500 -s 500 -t -k -P f:95
  2. 0 00:00:01 | IRQ Timer Latency (us) | Thread Timer Latency (us)
  3. CPU COUNT | cur min avg max | cur min avg max
  4. 0 #1015 | 236 37 42 236 | 594 213 227 594
  5. ---------------|----------------------------------------|---------------------------------------
  6. ALL #1015 e0 | 37 42 236 | 213 227 594
  7. rtla timerlat hit stop tracing
  8. ## CPU 0 hit stop tracing, analyzing it ##
  9. IRQ handler delay: 157.68 us (26.52 %)
  10. IRQ latency: 236.24 us
  11. Timerlat IRQ duration: 242.08 us (40.72 %)
  12. Blocking thread: 101.84 us (17.13 %)
  13. rtla:145 101.84 us
  14. Blocking thread stack trace
  15. -> stack_trace_save
  16. -> timerlat_save_stack.constprop.0
  17. -> timerlat_irq
  18. -> trace_event_buffer_commit
  19. -> __hrtimer_run_queues.constprop.0
  20. -> hrtimer_interrupt
  21. -> riscv_timer_interrupt
  22. -> handle_percpu_devid_irq
  23. -> ring_buffer_map
  24. -> handle_irq_desc
  25. -> riscv_intc_irq
  26. -> handle_riscv_irq
  27. ------------------------------------------------------------------------
  28. Thread latency: 594.48 us (100%)

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

2 交叉编译

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

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

  1. $ git clone git://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git
  2. $ cd libtraceevent/
  3. $ 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
  4. $ sudo make install
  5. $ cd ..
  6. $ git clone git://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git
  7. $ cd libtracefs/
  8. $ 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 源码目录下进行编译即可:

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

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

2.1 编译问题

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

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

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

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

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

  1. #define _GNU_SOURCE

3 使用方法

3.1 内核配置

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

  1. Kernel hacking --->
  2. Tracers(FTRACE [=y]) --->
  3. Timerlat tracer(TIMERLAT_TRACER [=y])

3.2 常用参数

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[smhd]:设置测试过程的持续时间。
-P, –priority o:prior:priof:priod:runtime:period:设置测试线程的调度参数,例如 -P f:95 代表使用 SCHED_FIFO 调度策略且优先级为 95。o 代表 SCHED_OTHER,r 代表使用 SCHED_RR,f 代表使用 SCHED_FIFO。

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

3.3 使用案例

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

  1. 0 00:00:01 | IRQ Timer Latency (us) | Thread Timer Latency (us)
  2. CPU COUNT | cur min avg max | cur min avg max
  3. 0 #1015 | 236 37 42 236 | 594 213 227 594
  4. ---------------|----------------------------------------|---------------------------------------
  5. ALL #1015 e0 | 37 42 236 | 213 227 594
  6. rtla timerlat hit stop tracing
  7. ## CPU 0 hit stop tracing, analyzing it ##
  8. IRQ handler delay: 157.68 us (26.52 %)
  9. IRQ latency: 236.24 us
  10. Timerlat IRQ duration: 242.08 us (40.72 %)
  11. Blocking thread: 101.84 us (17.13 %)
  12. rtla:145 101.84 us
  13. Blocking thread stack trace
  14. -> stack_trace_save
  15. -> timerlat_save_stack.constprop.0
  16. -> timerlat_irq
  17. -> trace_event_buffer_commit
  18. -> __hrtimer_run_queues.constprop.0
  19. -> hrtimer_interrupt
  20. -> riscv_timer_interrupt
  21. -> handle_percpu_devid_irq
  22. -> ring_buffer_map
  23. -> handle_irq_desc
  24. -> riscv_intc_irq
  25. -> handle_riscv_irq
  26. ------------------------------------------------------------------------
  27. 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 分别代表测试数据中的当前值、最小值、平均值、最大值。

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

4 总结

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

5 参考资料



Read Album:

Read Related:

Read Latest: