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(per-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
可以通过读取 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)外,追踪器会在每个运行 osnoise/ 线程的 CPU 的每个周期结束时打印一条消息。osnoise 特定的字段报告了:
RUNTIME IN US报告了 osnoise 线程持续循环读取时间所花费的时长(以微秒为单位)。
NOISE IN US报告了 osnoise 追踪器在相关运行期间观察到的噪声总和(以微秒为单位)。
% OF CPU AVAILABLE报告了在运行时间窗口内可供 osnoise 线程使用的 CPU 百分比。
MAX SINGLE NOISE IN US报告了在运行时间窗口内观察到的最大单次噪声(以微秒为单位)。干扰计数器(Interference counters)显示了在运行时间窗口内各自干扰发生的次数。
请注意,上面的示例显示了大量的硬件(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选项。特殊的DEFAULTS选项会将所有选项重置为默认值。
追踪器选项¶
osnoise/options 文件为 osnoise 追踪器提供了一组开关配置选项。这些选项是:
DEFAULTS:将选项重置为默认值。
OSNOISE_WORKLOAD:不分发 osnoise 工作负载(请参见下面的专门章节)。
PANIC_ON_STOP:如果追踪器停止,则调用panic()。此选项用于捕获 vmcore。
OSNOISE_PREEMPT_DISABLE:在运行 osnoise 工作负载时禁用抢占,仅允许 IRQ 和硬件相关的噪声。
OSNOISE_IRQ_DISABLE:在运行 osnoise 工作负载时禁用 IRQ,仅允许 NMI 和硬件相关的噪声(类似于 hwlat 追踪器)。
附加追踪¶
除了追踪器之外,还添加了一组追踪点(tracepoints)以方便识别 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 中报告的 8 微秒。其原因在于任何干扰执行前后所发生的进入和退出代码的开销。这就证明了采用双重方法的合理性:测量线程和追踪。
在没有工作负载的情况下运行 osnoise 追踪器¶
通过在设置了 NO_OSNOISE_WORKLOAD 选项的情况下启用 osnoise 追踪器,osnoise: 追踪点可用于测量任何类型 Linux 任务的执行时间,且不受其他任务的干扰。