系统范围的分析器(例如 perf)如何将计数器与指令相关联?

How does a system wide profiler (e.g. perf) correlate counters with instructions?

我正在尝试了解系统范围的分析器是如何工作的。我们以 linux perf 为例。对于一定的分析时间,它可以提供:

我几乎可以肯定的第一件事是,该报告只是对实际情况的估计。所以我认为有一些内核模块 以特定的采样率 启动软件中断。采样率越低,探查器开销越低。中断可以读取存储性能计数器的模型特定寄存器。

下一部分是将计数器与机器上 运行 的软件相关联。 那是我不明白的部分

  1. 那么探查器从哪里获取数据呢?

  2. 你可以询问任务调度器,看看你打断他时 运行 是什么吗? 这不会影响 调度程序的执行(例如,而不是继续 中断的功能,它只会安排另一个,使 探查器结果不准确)。 task_struct 对象的列表是否可用?

  3. 探查器如何关联硬件 指标甚至在指令级别?

这几乎回答了您的所有三个问题。

分析包括两种类型:计数和抽样。计数措施 全面的 数字 整个执行过程中的事件而不提供任何洞察力 关于 这 指令或函数 生成的 他们 .在 另一方面, 抽样给出了相关性 代码的事件 通过捕获的指令指针样本 . 采样时, 内核指示处理器在以下情况下发出中断 被选中的 事件计数器超过 临界点。吨 他的中断被内核和采样数据捕获 包括说明书 指针 值存储到环形缓冲区中。缓冲区由用户空间定期轮询 性能工具及其内容 写入磁盘。 在post处理中,Instruction Pointer匹配到 二进制文件中的地址,可以翻译成函数名等

参考http://openlab.web.cern.ch/sites/openlab.web.cern.ch/files/technical_documents/TheOverheadOfProfilingUsingPMUhardwareCounters.pdf

So I think there's some kernel module that launches software interrupts at a certain sampling rate.

Perf 不是模块,它是 Linux 内核的一部分,在 kernel/events/core.c and for every supported architecture and cpu model, for example arch/x86/kernel/cpu/perf_event*.c。但 Oprofile 是一个模块,具有类似的方法。

Perf 通常通过请求 CPU 的 PMU(性能监控单元)在某些硬件性能计数器(Yokohama, slide 5 "• 达到阈值时中断: 允许采样")。实际上可能实现为:

  • select 一些 PMU 计数器
  • 将其初始化为-N,其中N是采样周期(我们希望在N个事件后中断,例如,在200万个周期后perf record -c 2000000 -e cycles,或者由perf计算和调整的一些N当没有设置额外选项或给出 -F 时)
  • 将此计数器设置为需要的事件,并要求 PMU 在溢出时生成中断 (ARCH_PERFMON_EVENTSEL_INT)。它会在我们的计数器递增 N 之后发生。

所有现代 Intel 芯片都支持此功能,例如 Nehalem:https://software.intel.com/sites/default/files/76/87/30320 - Nehalem 性能监控单元编程指南

EBS - Event Based Sampling. A technique in which counters are pre-loaded with a large negative count, and they are configured to interrupt the processor on overflow. When the counter overflows the interrupt service routine capture profiling data.

因此,当您使用硬件 PMU 时,在定时器中断时不需要额外的工作来专门读取硬件 PMU 计数器。在任务切换时 save/restore PMU 状态有一些工作,但是 kernel/events/core.c 的 *_sched_in/*_sched_out 不会更改当前线程的 PMU 计数器值,也不会将其导出到用户-space.

有一个处理程序:arch/x86/kernel/cpu/perf_event.c: x86_pmu_handle_irq which finds the overflowed counter and calls perf_sample_data_init(&data, 0, event->hw.last_period); 记录当前时间,最后执行命令的IP(由于大多数英特尔微架构的乱序性,它可能不准确,有对于某些事件 - PEBS,perf record -e cycles:pp),堆栈跟踪数据(如果在记录中使用了 -g)等是有限的解决方法。然后处理程序将计数器值重置为 -N(x86_perf_event_set_period, wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask); - 注意 left)

之前的减号

The lower the sampling rate, the lower the profiler overhead.

Perf 允许您使用 -F 选项设置目标采样率,-F 1000 表示大约 1000 irq/s。由于高开销,不建议使用高速率。十年前,英特尔 VTune 建议不要超过 1000 irq/s (http://www.cs.utah.edu/~mhall/cs4961f09/VTune-1.pdf尝试在每个逻辑 CPU. 每秒获取大约 1000 个样本” ), perf 通常不允许非 root 用户使用过高的速率(当 "perf interrupt took too long" 时自动调低速率 - 检查你的 dmesg;同时检查 sysctl -a|grep perf,例如 kernel.perf_cpu_time_max_percent=25 - 这意味着 perf 将尝试使用不超过 CPU)

的 25%

Can you interrogate for example the task scheduler to find out what was running when you interrupted him?

没有。但是您可以在 sched_switch 或其他计划事件中启用跟踪点(列出计划中所有可用的:perf list 'sched:*'),并将其用作 perf 的分析事件。您甚至可以要求 perf 在此跟踪点记录堆栈跟踪:

 perf record -a -g -e "sched:sched_switch" sleep 10

Won't that affect the execution of the scheduler

启用跟踪点将使添加一些性能事件采样工作到具有跟踪点的函数

Is the list of task_struct objects available?

仅通过 ftrace...

Information about context switches

这是软件性能事件,只需使用 sched/core.c 中的 PERF_COUNT_SW_CONTEXT_SWITCHES 事件调用 perf_sw_event(间接)。直接调用示例-迁移软件事件:kernel/sched/core.c set_task_cpu()p->se.nr_migrations++; perf_sw_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1, NULL, 0);

PS:Gregg 在 Linux 中有关于 perf、ftrace 和其他分析和跟踪子系统的精彩幻灯片:http://www.brendangregg.com/linuxperf.html