OSNOISE 跟踪器

在高 性能计算 (HPC) 的背景下,操作系统噪声(osnoise)指的是由于操作系统内部的活动而导致应用程序受到的干扰。在 Linux 的背景下,NMI、IRQ、SoftIRQ 和任何其他系统线程都可能对系统造成噪声。此外,与硬件相关的工作也可能通过 SMI 等方式产生噪声。

hwlat_detector 是用于识别最复杂噪声源之一的工具:硬件噪声

简而言之,hwlat_detector 会创建一个线程,该线程会以给定的周期定期运行。在一个周期的开始,该线程会禁用中断并开始采样。在运行期间,hwlatd 线程会循环读取时间。由于中断被禁用,线程、IRQ 和 SoftIRQ 无法干扰 hwlatd 线程。因此,两次不同的时间读取之间任何差距的原因要么在于 NMI,要么在于硬件本身。在该周期的结束,hwlatd 会启用中断并报告读取之间观察到的最大差距。它还会打印 NMI 发生计数器。如果输出没有报告 NMI 执行,用户可以得出结论,硬件是延迟的罪魁祸首。hwlat 通过观察 NMI 的进入和退出来检测 NMI 的执行。

osnoise 跟踪器通过运行类似的循环来利用 hwlat_detector,该循环启用抢占、SoftIRQ 和 IRQ,从而允许在其执行期间出现所有 osnoise 源。使用与 hwlat 相同的方法,osnoise 记录任何干扰源的进入和退出点,从而增加每个 CPU 的干扰计数器。osnoise 跟踪器还为每个干扰源保存一个干扰计数器。每当该工具观察到这些干扰的进入事件时,NMI、IRQ、SoftIRQ 和线程的干扰计数器都会增加。当发生噪声且没有任何来自操作系统级别的干扰时,硬件噪声计数器会增加,指向与硬件相关的噪声。通过这种方式,osnoise 可以解释任何干扰源。在该周期的结束,osnoise 跟踪器会打印所有噪声的总和、最大单噪声、线程可用的 CPU 百分比以及噪声源的计数器。

用法

将 ASCII 文本“osnoise”写入跟踪系统的 current_tracer 文件(通常挂载在 /sys/kernel/tracing)。

例如

[root@f32 ~]# cd /sys/kernel/tracing/
[root@f32 tracing]# echo osnoise > current_tracer

可以通过读取跟踪文件来跟踪跟踪

[root@f32 tracing]# cat trace
# tracer: osnoise
#
#                                _-----=> irqs-off
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth                            MAX
#                              || /                                             SINGLE     Interference counters:
#                              ||||               RUNTIME      NOISE   % OF CPU  NOISE    +-----------------------------+
#           TASK-PID      CPU# ||||   TIMESTAMP    IN US       IN US  AVAILABLE  IN US     HW    NMI    IRQ   SIRQ THREAD
#              | |         |   ||||      |           |             |    |            |      |      |      |      |      |
           <...>-859     [000] ....    81.637220: 1000000        190  99.98100       9     18      0   1007     18      1
           <...>-860     [001] ....    81.638154: 1000000        656  99.93440      74     23      0   1006     16      3
           <...>-861     [002] ....    81.638193: 1000000       5675  99.43250     202      6      0   1013     25     21
           <...>-862     [003] ....    81.638242: 1000000        125  99.98750      45      1      0   1011     23      0
           <...>-863     [004] ....    81.638260: 1000000       1721  99.82790     168      7      0   1002     49     41
           <...>-864     [005] ....    81.638286: 1000000        263  99.97370      57      6      0   1006     26      2
           <...>-865     [006] ....    81.638302: 1000000        109  99.98910      21      3      0   1006     18      1
           <...>-866     [007] ....    81.638326: 1000000       7816  99.21840     107      8      0   1016     39     19

除了常规跟踪字段(从 TASK-PID 到 TIMESTAMP)之外,跟踪器会在每个周期的末尾为每个正在运行 osnoise/ 线程的 CPU 打印一条消息。osnoise 特定字段报告

  • RUNTIME IN US 报告 osnoise 线程保持循环读取时间的时间量(以微秒为单位)。

  • NOISE IN US 报告 osnoise 跟踪器在关联的运行时期间观察到的噪声总和(以微秒为单位)。

  • % OF CPU AVAILABLE 报告运行时窗口期间 osnoise 线程可用的 CPU 百分比。

  • MAX SINGLE NOISE IN US 报告运行时窗口期间观察到的最大单噪声。

  • 干扰计数器显示在运行时窗口期间发生各自的干扰次数。

请注意,上面的示例显示了大量的 HW 噪声样本。原因是此样本是在虚拟机上采集的,并且主机干扰被检测为硬件干扰。

跟踪器配置

跟踪器在 osnoise 目录中有一组选项,它们是

  • osnoise/cpus:osnoise 线程将在其上执行的 CPU。

  • osnoise/period_us:osnoise 线程的周期。

  • osnoise/runtime_us:osnoise 线程将寻找噪声的时间长度。

  • osnoise/stop_tracing_us:如果发生高于配置值的单个噪声,则停止系统跟踪。写入 0 会禁用此选项。

  • osnoise/stop_tracing_total_us:如果总噪声高于配置的值,则停止系统跟踪。写入 0 会禁用此选项。

  • tracing_threshold:两次 time() 读取之间被视为噪声的最小增量,以微秒为单位。当设置为 0 时,将使用默认值,该值当前为 1 微秒。

  • osnoise/options:一组可以启用(通过将选项名称写入文件)或禁用(通过写入带有“NO_”前缀的选项名称)的开/关选项。例如,写入 NO_OSNOISE_WORKLOAD 会禁用 OSNOISE_WORKLOAD 选项。特殊的 DEAFAULTS 选项会将所有选项重置为默认值。

跟踪器选项

osnoise/options 文件公开了一组 osnoise 跟踪器的开/关配置选项。这些选项是

  • DEFAULTS:将选项重置为默认值。

  • OSNOISE_WORKLOAD:不调度 osnoise 工作负载(请参阅下面的专用部分)。

  • PANIC_ON_STOP:如果跟踪器停止,则调用 panic()。此选项用于捕获 vmcore。

  • OSNOISE_PREEMPT_DISABLE:在运行 osnoise 工作负载时禁用抢占,仅允许 IRQ 和与硬件相关的噪声。

  • OSNOISE_IRQ_DISABLE:在运行 osnoise 工作负载时禁用 IRQ,仅允许 NMI 和与硬件相关的噪声,如 hwlat 跟踪器。

其他跟踪

除了跟踪器之外,还添加了一组跟踪点,以方便识别 osnoise 源。

  • osnoise:sample_threshold:在噪声高于可配置的 tolerance_ns 时打印。

  • osnoise:nmi_noise:来自 NMI 的噪声,包括持续时间。

  • osnoise:irq_noise:来自 IRQ 的噪声,包括持续时间。

  • osnoise:softirq_noise:来自 SoftIRQ 的噪声,包括持续时间。

  • osnoise:thread_noise:来自线程的噪声,包括持续时间。

请注意,所有值都是净值。例如,如果在 osnoise 运行时,另一个线程抢占了 osnoise 线程,它会在开始时启动 thread_noise 持续时间。然后,发生 IRQ,抢占 thread_noise,启动 irq_noise。当 IRQ 结束其执行时,它将计算其持续时间,并且该持续时间将从 thread_noise 中减去,以避免重复计算 IRQ 执行。此逻辑适用于所有噪声源。

这是一个使用这些跟踪点的示例

  osnoise/8-961     [008] d.h.  5789.857532: irq_noise: local_timer:236 start 5789.857529929 duration 1845 ns
  osnoise/8-961     [008] dNh.  5789.858408: irq_noise: local_timer:236 start 5789.858404871 duration 2848 ns
migration/8-54      [008] d...  5789.858413: thread_noise: migration/8:54 start 5789.858409300 duration 3068 ns
  osnoise/8-961     [008] ....  5789.858413: sample_threshold: start 5789.858404555 duration 8812 ns interferences 2

在此示例中,最后一行报告了 8 微秒的噪声样本,指向了两次干扰。在跟踪中向后看,之前的两个条目是关于在定时器 IRQ 执行后运行的迁移线程。第一个事件不是噪声的一部分,因为它发生在 1 毫秒之前。

值得注意的是,跟踪点中报告的持续时间之和小于 sample_threshold 中报告的 8 微秒。原因在于任何干扰执行之前和之后发生的入口和出口代码的开销。这证明了双重方法的合理性:测量线程和跟踪。

在没有工作负载的情况下运行 osnoise 跟踪器

通过启用设置了 NO_OSNOISE_WORKLOAD 选项的 osnoise 跟踪器,osnoise:跟踪点可用于测量任何类型的 Linux 任务的执行时间,不受其他任务的干扰。