[...]
在大多数情况下,这些
/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_tsc
和nonstop_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 必须保持在线...”)
菜单“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. )
*/