OSNOISE Tracer

在高性能计算(HPC)的上下文中,操作系统噪声(osnoise)指的是应用程序由于操作系统内部的活动而受到的干扰。在 Linux 的上下文中,NMIs、IRQs、SoftIRQs 以及任何其他系统线程都可能导致系统噪声。此外,与硬件相关的工作也可能通过 SMI 等方式造成噪声。

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

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

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

用法

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

例如

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

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

[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)之外,tracer 还在每个周期结束时为每个运行 osnoise/ 线程的 CPU 打印一条消息。 osnoise 特定字段报告

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

  • NOISE IN US 报告 osnoise tracer 在相关运行时观察到的噪声总和(以微秒为单位)。

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

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

  • 干扰计数器显示在运行时窗口期间发生每个相应干扰的次数。

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

Tracer 配置

tracer 在 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() 读取之间的最小增量,单位为 us。设置为 0 时,将使用默认值,当前为 1 us。

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

Tracer 选项

osnoise/options 文件公开了 osnoise tracer 的一组 on/off 配置选项。这些选项是

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

  • OSNOISE_WORKLOAD:不分派 osnoise 工作负载(参见下面的专用部分)。

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

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

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

其他跟踪

除了 tracer 之外,还添加了一组跟踪点,以方便识别 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 执行之后运行的迁移线程。 第一个事件不是噪声的一部分,因为它发生在一毫秒之前。

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

在没有工作负载的情况下运行 osnoise tracer

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