Documentation/cpu-load.txt 表示 Linux cpu 负载 *可能* 具有误导性。是否有未提及的新(或旧)缓解措施?

Documentation/cpu-load.txt 表示 Linux cpu 负载 *可能* 具有误导性。是否有未提及的新(或旧)缓解措施?

linux-5.1/文档/cpu-load.txt

[...]

在大多数情况下,这些/proc/stat信息非常接近地反映了现实,但是由于内核如何/何时收集这些数据的性质,有时它根本不可信。

[...]

如果我们想象系统有一个任务以下列方式定期燃烧周期:

 time line between two timer interrupts
|--------------------------------------|
 ^                                    ^
 |_ something begins working          |
                                      |_ something goes to sleep
                                     (only to be awaken quite soon)

在上述情况下,系统的负载将是 0% /proc/stat(因为当系统执行空闲处理程序时,定时器中断总是会发生),但实际上负载接近 99%。

该文件于 2007 年添加。

例如,是否修改了CPU调度程序(例如schedule()函数)来测量每次进程从可运行状态转换到等待状态时的时间,是否有足够便宜且可靠的时间源(可靠的 TSC)?

该文档包括一个示例程序,smallhog.c.根据 LKML.org 上的链接线程,它能够占用 CPU,并且内核仅报告百分之几或更少的 CPU 使用率。

我尝试在当前系统上编译并运行它。内核报告该程序的 CPU 使用率约为 80%。所以情况似乎发生了一些变化。我们是否确切地知道为什么smallhog.c该系统效率较低?

我使用 Fedora 30,Linux 内核 v5.2.0-rc5(大约),在“Intel(R) Core(TM) i5-5300U CPU”上以 64 位模式运行。

  • lscpu显示constant_tscnonstop_tsc
  • journalctl -k | grep -iE "TSC|clocksource"看起来内核没有发现 TSC 的问题。
  • cat /sys/devices/system/clocksource/clocksource0显示“tsc”。

我看到链接的线程说

并非所有架构都是如此,有些架构通过记录用户/内核/中断转换的时间来进行更准确的统计......
的确。不过,这肯定是常见的、更无聊的电脑架构的做法。

(或许赫蒂克事态发展可能会对这个问题产生影响吗?即使只是为了使其更难以被利用。或者更容易?或者只需要稍微不同的代码来利用?)。

答案1

你说该smallhog进程显示 80% CPU 时间。 CPU 上剩余 20% 的时间用于中断! 为什么 Smallhog.c 在我的系统上显示 CPU 使用率低于 100%?

smallhog正在做一些中断密集型的事情。其具体战术显然是被击败了IRQ_TIME_ACCOUNTING。见下文。

我怀疑仍然有办法避开计时器滴答声:-)。您可能需要一种聪明的方法来预测蜱虫何时会触发。例如,通过查看/proc/interrupts.

config IRQ_TIME_ACCOUNTING
    bool "Fine granularity task level IRQ time accounting"
    depends on HAVE_IRQ_TIME_ACCOUNTING && !VIRT_CPU_ACCOUNTING_NATIVE
    help
      Select this option to enable fine granularity task irq time
      accounting. This is done by reading a timestamp on each
      transitions between softirq and hardirq state, so there can be a
      small performance impact.

      If in doubt, say N here.

该功能在 Fedora 内核配置中启用(请参阅 参考资料/boot/config-*)。在 x86 CPU 上,它使用 TSC。可以使用启动时选项禁用该功能,tsc=noirqtime.[*]

更准确的核算方法

正如问题中提到的,PowerPC / S390 有特定的代码可以计算每个上下文切换的 CPU 时间。这就是所谓的VIRT_CPU_ACCOUNTING_NATIVE。但你的 x86 内核没有这个。

有一个通用的等效项,称为VIRT_CPU_ACCOUNTING_GEN. (GEN 是“通用”的缩写)。此功能内置于您的 Fedora 内核中。但默认情况下此功能并未激活。

你必须仔细阅读:-)。 VIRT_CPU_ACCOUNTING_GEN 仅有的在“full dynticks systems”上变得活跃。虽然Fedora内核配置包括NO_HZ_FULL,Fedora 默认情况下不启用“full dynticks”。启用“full dynticks”需要在启动时指定一个选项,nohz_full=以及“adaptive-ticks CPU”列表。 (“最后一个-adaptive-tick CPU 必须保持在线...”)

linux-5.2-rc5/init/Kconfig:

菜单“CPU/任务时间和统计统计”

配置VIRT_CPU_ACCOUNTING
    布尔值

选择
    提示“CPU时间统计”
    默认 TICK_CPU_ACCOUNTING 如果 !PPC64
    如果 PPC64,则默认 VIRT_CPU_ACCOUNTING_NATIVE

# 一种用于纯粹基于时钟周期的 cputime 记账的存根配置
配置TICK_CPU_ACCOUNTING
    bool "基于简单滴答的 cputime 会计"
    取决于!S390 && !NO_HZ_FULL
    帮助
      这是基于基本时钟周期的 cputime 统计,它维护
      有关用户、系统和每个 jiffies 上花费的空闲时间的统计信息
      粒度。

      如果不确定,请选 Y。

配置VIRT_CPU_ACCOUNTING_NATIVE
    bool“确定性任务和 CPU 时间统计”
    取决于 HAVE_VIRT_CPU_ACCOUNTING && !NO_HZ_FULL
    选择VIRT_CPU_ACCOUNTING
    帮助
      选择此选项可启用更准确的任务和 CPU 时间
      会计。这是通过读取每个处理器上的 CPU 计数器来完成的。
      内核进入和退出以及内核内的转换
      系统、软中断和硬中断状态之间,因此存在一个
      性能影响小。在 s390 或 IBM POWER > 5 的情况下,
      这还可以对逻辑分区上的被盗时间进行统计
      系统。

配置VIRT_CPU_ACCOUNTING_GEN
    bool "Full dynticks CPU 时间统计"
    取决于 HAVE_CONTEXT_TRACKING
    取决于 HAVE_VIRT_CPU_ACCOUNTING_GEN
    取决于 GENERIC_CLOCKEVENTS
    选择VIRT_CPU_ACCOUNTING
    选择上下文跟踪
    帮助
      选择此选项可全面启用任务和 CPU 时间统计
      dynticks系统。这种会计是通过观察每一个来实现的
      使用上下文跟踪子系统的内核-用户边界。
      因此,会计的执行是以牺牲一些重要的费用为代价的。
      高架。

      目前,这仅在您正在处理完整的工作时才有用
      dynticks子系统开发。

      如果不确定,请选 N。

最终选择

我在最后一段中划了一条线,因为它已经过时了。 “完整的dynticks子系统”现已开发出来。

[*] TSC 注意事项

如果 x86 CPU 没有 TSC,内核不会尝试使用任何其他硬件时钟源 for IRQ_TIME_ACCOUNTING(或 for VIRT_CPU_ACCOUNTING_GEN)。

该代码表明接受任何可用的 TSC。我不知道这对于没有CPU的CPU来说效果如何constant_tsc:-)。尽管我 99.9% 确信相关维护人员已经意识到这个问题,并且会问为什么它是可以接受的。

native_sched_clock()tsc_init():

/*
 * Fall back to jiffies if there's no TSC available:
 * ( But note that we still use it if the TSC is marked
 *   unstable. We do this because unlike Time Of Day,
 *   the scheduler clock tolerates small errors and it's
 *   very important for it to be as fast as the platform
 *   can achieve it. )
 */

相关内容