调度器统计

schedstats 第 17 版移除了“lb_imbalance”字段,因为它不再有意义,而是添加了更相关的字段,即“lb_imbalance_load”、“lb_imbalance_util”、“lb_imbalance_task”和“lb_imbalance_misfit”。从该版本开始,domain 字段会打印相应调度域的名称。

schedstats 第 16 版更改了“enum cpu_idle_type”中定义的顺序,这改变了 show_schedstat() 中 [CPU_MAX_IDLE_TYPES] 列的顺序。特别是 CPU_IDLE 和 __CPU_NOT_IDLE 的位置发生了变化。数组的大小不变。

schedstats 第 15 版去掉了 sched_yield 的一些计数器:yld_exp_empty、yld_act_empty 和 yld_both_empty。除此之外,它与第 14 版相同。详细信息可在以下网址获取:

schedstats 第 14 版包含了对 sched_domains 的支持,该支持在 2.6.20 版进入主线内核,尽管它与 2.6.13-2.6.19 内核中的第 12 版统计数据相同(第 13 版从未发布内核版本)。一些计数器更适合按运行队列(per-runqueue)统计;另一些则适合按域(per-domain)统计。请注意,域(及其相关信息)仅在使用了 CONFIG_SMP 的机器上才相关并可用。

在 schedstat 第 14 版中,每个列出的 CPU 至少有一个域统计级别,并且很可能不止一个域。在当前实现中,域没有特定的名称,但编号最高的域通常协调机器上所有 CPU 的平衡,而 domain0 是最集中关注的域,有时仅在 CPU 对之间进行平衡。目前,没有架构需要超过三个域级别。域统计中的第一个字段是一个位掩码,指示哪些 CPU 受该域影响。详细信息可在以下网址获取:

schedstat 文档从第 10 版开始维护,未针对第 11 和 12 版进行更新。第 10 版的详细信息可在以下网址获取:

这些字段是计数器,只会递增。使用这些字段的程序需要从一个基准观察开始,然后计算每次后续观察中计数器的变化。一个针对其中许多字段执行此操作的 Perl 脚本可在以下网址获取:

请注意,任何此类脚本都必然是特定于版本的,因为更改版本的主要原因是输出格式的变化。对于希望编写自己脚本的人,此处描述了这些字段。

CPU 统计信息

cpu<N> 1 2 3 4 5 6 7 8 9

第一个字段是 sched_yield() 统计信息

  1. sched_yield() 被调用的次数

接下来的三个是 schedule() 统计信息

  1. 此字段是 O(1) 调度器中使用的传统数组过期计数字段。我们保留它是为了 ABI 兼容性,但它总是设置为零。

  2. schedule() 被调用的次数

  3. schedule() 使处理器空闲的次数

接下来的两个是 try_to_wake_up() 统计信息

  1. try_to_wake_up() 被调用的次数

  2. try_to_wake_up() 被调用以唤醒本地 CPU 的次数

接下来的三个是描述调度延迟的统计信息

  1. 此处理器上任务运行的总时间(纳秒)

  2. 此处理器上任务等待运行的总时间(纳秒)

  3. 此 CPU 上运行的时间片数量

域统计信息

为每个描述的 CPU 的每个域生成一个。 (请注意,如果未定义 CONFIG_SMP,则不使用任何域,并且这些行不会出现在输出中。<name> 是 domain 字段的一个扩展,它打印相应调度域的名称。它可以在 schedstat 17 及更高版本中出现。

domain<N> <name> <cpumask> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

第一个字段是一个位掩码,指示此域操作的 CPU。

接下来的 33 个是 sched_balance_rq() 的各种统计信息,按空闲类型(忙碌、空闲和刚空闲)分组

  1. 在此域中,当 CPU 忙碌时 sched_balance_rq() 被调用的次数

  2. 在此域中,当 CPU 忙碌时 sched_balance_rq() 检查但发现负载不需要平衡的次数

  3. 在此域中,当 CPU 忙碌时 sched_balance_rq() 尝试移动一个或多个任务但失败的次数

  4. 当 CPU 忙碌时负载的总不平衡量

  5. 当 CPU 忙碌时利用率的总不平衡量

  6. 当 CPU 忙碌时任务数量的总不平衡量

  7. 当 CPU 忙碌时由于不适合的任务造成的总不平衡量

  8. 在此域中,当 CPU 忙碌时 pull_task() 被调用的次数

  9. 在此域中,当 CPU 忙碌时,即使目标任务是缓存热点,pull_task() 仍被调用的次数

  10. 在此域中,当 CPU 忙碌时 sched_balance_rq() 被调用但未找到更忙队列的次数

  11. 在此域中,当 CPU 忙碌时找到了更忙队列但未找到更忙组的次数

  12. 在此域中,当 CPU 空闲时 sched_balance_rq() 被调用的次数

  13. 在此域中,当 CPU 空闲时 sched_balance_rq() 检查但发现负载不需要平衡的次数

  14. 在此域中,当 CPU 空闲时 sched_balance_rq() 尝试移动一个或多个任务但失败的次数

  15. 当 CPU 空闲时负载的总不平衡量

  16. 当 CPU 空闲时利用率的总不平衡量

  17. 当 CPU 空闲时任务数量的总不平衡量

  18. 当 CPU 空闲时由于不适合的任务造成的总不平衡量

  19. 在此域中,当 CPU 空闲时 pull_task() 被调用的次数

  20. 在此域中,当 CPU 空闲时,即使目标任务是缓存热点,pull_task() 仍被调用的次数

  21. 在此域中,当 CPU 空闲时 sched_balance_rq() 被调用但未找到更忙队列的次数

  22. 在此域中,当 CPU 空闲时找到了更忙队列但未找到更忙组的次数

  23. 在此域中,当 CPU 刚变为空闲时 sched_balance_rq() 被调用的次数

  24. 在此域中,当 CPU 刚变为空闲时 sched_balance_rq() 检查但发现负载不需要平衡的次数

  25. 在此域中,当 CPU 刚变为空闲时 sched_balance_rq() 尝试移动一个或多个任务但失败的次数

  26. 当 CPU 刚变为空闲时负载的总不平衡量

  27. 当 CPU 刚变为空闲时利用率的总不平衡量

  28. 当 CPU 刚变为空闲时任务数量的总不平衡量

  29. 当 CPU 刚变为空闲时由于不适合的任务造成的总不平衡量

  30. 在此域中,当刚变为空闲时 pull_task() 被调用的次数

  31. 在此域中,当刚变为空闲时,即使目标任务是缓存热点,pull_task() 仍被调用的次数

  32. 在此域中,当 CPU 刚变为空闲时 sched_balance_rq() 被调用但未找到更忙队列的次数

  33. 在此域中,当 CPU 刚变为空闲时找到了更忙队列但未找到更忙组的次数

接下来的三个是 active_load_balance() 统计信息

  1. active_load_balance() 被调用的次数

  2. active_load_balance() 尝试移动任务但失败的次数

  3. active_load_balance() 成功移动任务的次数

接下来的三个是 sched_balance_exec() 统计信息

  1. sbe_cnt 未使用

  2. sbe_balanced 未使用

  3. sbe_pushed 未使用

接下来的三个是 sched_balance_fork() 统计信息

  1. sbf_cnt 未使用

  2. sbf_balanced 未使用

  3. sbf_pushed 未使用

接下来的三个是 try_to_wake_up() 统计信息

  1. 在此域中,try_to_wake_up() 唤醒了上次在此域中不同 CPU 上运行的任务的次数

  2. 在此域中,try_to_wake_up() 将任务移动到唤醒 CPU 的次数,因为该任务在其自己的 CPU 上无论如何都是缓存冷点

  3. 在此域中,try_to_wake_up() 启动被动平衡的次数

/proc/<pid>/schedstat

schedstats 还添加了一个新的 /proc/<pid>/schedstat 文件,以包含一些相同的进程级别信息。此文件中包含三个字段,对应于该进程的:

  1. 在 CPU 上花费的时间(纳秒)

  2. 在运行队列中等待的时间(纳秒)

  3. 此 CPU 上运行的时间片数量

可以很容易地编写一个程序来利用这些额外字段,以报告特定进程或进程集在调度器策略下的表现。此类程序的一个简单版本可在以下网址获取: