DTL (Dispatch Trace Log)¶
Athira Rajeev, 2025年4月19日
基本概述¶
pseries 共享处理器逻辑分区 (SPLPAR) 机器可以使用来自调度跟踪日志 (DTL) 缓冲区的数据,从 hypervisor 检索调度和抢占事件的日志。利用此信息,用户可以了解每次调度和抢占发生的时间以及原因。vpa-dtl PMU 通过 perf 公开虚拟处理器区域 (VPA) DTL 计数器。
使用的基础设施¶
VPA DTL PMU 计数器在溢出时不会中断或生成任何 PMI 中断。因此,使用 hrtimer 来轮询 DTL 数据。计时器间隔可以由用户通过以纳秒为单位的 sample_period 字段提供。每个 vpa-dtl pmu 线程添加了一个 hrtimer。DTL(调度跟踪日志)包含有关调度/抢占、入队时间等的信息。我们将 DTL 缓冲区数据直接复制为辅助缓冲区的一部分,并将在稍后处理它。这将避免在内核空间中创建样本所花费的时间。收集调度跟踪日志 (DTL) 条目的 PMU 驱动程序利用了 perf 基础设施中的 AUX 支持。在工具端,此数据作为 PERF_RECORD_AUXTRACE 记录提供。
为了将每个 DTL 条目与跨 CPU 的其他事件关联起来,为每个 CPU 创建了一个 auxtrace_queue。每个 auxtrace 队列都有一个 auxtrace 缓冲区的数组/列表。所有的 auxtrace 队列都在 auxtrace 堆中维护。这些队列根据时间戳进行排序。当处理不同的 PERF_RECORD_XX 记录时,将 perf 记录的时间戳与 auxtrace 堆中顶部元素的时间戳进行比较,以便将 DTL 事件与其他事件关联起来。如果堆中元素的时间戳低于 perf 记录中条目的时间戳,则处理 auxtrace 队列。有时可能会发生某个缓冲区仅被部分处理的情况。如果另一个事件发生的时间戳大于队列中当前处理的元素,它将转到下一个 perf record。因此需要跟踪缓冲区的位置以便下次继续处理。使用 auxtrace 缓冲区中最后处理的条目的时间戳更新 auxtrace 堆的时间戳。
该基础设施确保调度跟踪日志条目能够与其他事件(如 sched)关联并一起呈现。
vpa-dtl PMU 示例用法¶
# ls /sys/devices/vpa_dtl/
events format perf_event_mux_interval_ms power subsystem type uevent
要使用 perf record 捕获 DTL 数据:.. code-block:: sh
# ./perf record -a -e sched:*,vpa_dtl/dtl_all/ -c 1000000000 sleep 1
可以使用 perf 解释结果。perf report -D 的片段
# ./perf report -D
存在不同的 PERF_RECORD_XX 记录。其中与 auxtrace 缓冲区对应的记录包括
PERF_RECORD_AUX 传达 AUX 区域中有新数据可用
PERF_RECORD_AUXTRACE_INFO 描述缓冲区中 auxtrace 数据的偏移量和大小
PERF_RECORD_AUXTRACE 这是定义 auxtrace 数据的记录,在 vpa-dtl pmu 的情况下,这里是调度跟踪日志数据。
显示 PERF_RECORD_AUXTRACE 转储的 perf report -D 片段
0 0 0x39b10 [0x30]: PERF_RECORD_AUXTRACE size: 0x690 offset: 0 ref: 0 idx: 0 tid: -1 cpu: 0 . . ... VPA DTL PMU data: size 1680 bytes, entries is 35 . 00000000: boot_tb: 21349649546353231, tb_freq: 512000000 . 00000030: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:7064, ready_to_enqueue_time:187, waiting_to_ready_time:6611773 . 00000060: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:146, ready_to_enqueue_time:0, waiting_to_ready_time:15359437 . 00000090: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:4868, ready_to_enqueue_time:232, waiting_to_ready_time:5100709 . 000000c0: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:179, ready_to_enqueue_time:0, waiting_to_ready_time:30714243 . 000000f0: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:197, ready_to_enqueue_time:0, waiting_to_ready_time:15350648 . 00000120: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:213, ready_to_enqueue_time:0, waiting_to_ready_time:15353446 . 00000150: dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:212, ready_to_enqueue_time:0, waiting_to_ready_time:15355126 . 00000180: dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:6368, ready_to_enqueue_time:164, waiting_to_ready_time:5104665
以上是以下格式的 dtl 条目的表示形式
- struct dtl_entry {
u8 dispatch_reason; u8 preempt_reason; u16 processor_id; u32 enqueue_to_dispatch_time; u32 ready_to_enqueue_time; u32 waiting_to_ready_time; u64 timebase; u64 fault_addr; u64 srr0; u64 srr1;
};
前两个字段表示调度原因和抢占原因。对 PERF_RECORD_AUXTRACE 记录的后处理将转换为供用户使用的有意义的数据。
使用 perf report 可视化调度跟踪日志条目¶
# ./perf record -a -e sched:*,vpa_dtl/dtl_all/ -c 1000000000 sleep 1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.300 MB perf.data ]
# ./perf report
# Samples: 321 of event 'vpa-dtl'
# Event count (approx.): 321
#
# Children Self Command Shared Object Symbol
# ........ ........ ....... ................. ..............................
#
100.00% 100.00% swapper [kernel.kallsyms] [k] plpar_hcall_norets_notrace
使用 perf script 可视化调度跟踪日志条目¶
# ./perf script
migration/9 67 [009] 105373.359903: sched:sched_waking: comm=perf pid=13418 prio=120 target_cpu=009
migration/9 67 [009] 105373.359904: sched:sched_migrate_task: comm=perf pid=13418 prio=120 orig_cpu=9 dest_cpu=10
migration/9 67 [009] 105373.359907: sched:sched_stat_runtime: comm=migration/9 pid=67 runtime=4050 [ns]
migration/9 67 [009] 105373.359908: sched:sched_switch: prev_comm=migration/9 prev_pid=67 prev_prio=0 prev_state=S ==> next_comm=swapper/9 next_pid=0 next_prio=120
:256 256 [016] 105373.359913: vpa-dtl: timebase: 21403600706628832 dispatch_reason:decrementer interrupt, preempt_reason:H_CEDE, enqueue_to_dispatch_time:4854, ready_to_enqueue_time:139, waiting_to_ready_time:511842115 c0000000000fcd28 plpar_hcall_norets_notrace+0x18 ([kernel.kallsyms])
:256 256 [017] 105373.360012: vpa-dtl: timebase: 21403600706679454 dispatch_reason:priv doorbell, preempt_reason:H_CEDE, enqueue_to_dispatch_time:236, ready_to_enqueue_time:0, waiting_to_ready_time:133864583 c0000000000fcd28 plpar_hcall_norets_notrace+0x18 ([kernel.kallsyms])
perf 13418 [010] 105373.360048: sched:sched_stat_runtime: comm=perf pid=13418 runtime=139748 [ns]
perf 13418 [010] 105373.360052: sched:sched_waking: comm=migration/10 pid=72 prio=0 target_cpu=010