1 .. SPDX-License-Identifier: GPL-2.0 1 .. SPDX-License-Identifier: GPL-2.0 2 .. include:: ../disclaimer-zh_CN.rst 2 .. include:: ../disclaimer-zh_CN.rst 3 3 4 :Original: Documentation/scheduler/sched-stats 4 :Original: Documentation/scheduler/sched-stats.rst 5 5 6 :翻译: 6 :翻译: 7 7 8 唐艺舟 Tang Yizhou <tangyeechou@gmail.com> 8 唐艺舟 Tang Yizhou <tangyeechou@gmail.com> 9 9 10 ============== 10 ============== 11 调度器统计数据 11 调度器统计数据 12 ============== 12 ============== 13 13 14 第15版schedstats去掉了sched_yield的一 14 第15版schedstats去掉了sched_yield的一些计数器:yld_exp_empty,yld_act_empty 15 和yld_both_empty。在其它方面和第14版 15 和yld_both_empty。在其它方面和第14版完全相同。 16 16 17 第14版schedstats包括对sched_domains(译 17 第14版schedstats包括对sched_domains(译注:调度域)的支持,该特性进入内核 18 主线2.6.20,不过这一版schedstats与2.6 18 主线2.6.20,不过这一版schedstats与2.6.13-2.6.19内核的版本12的统计数据是完全 19 相同的(内核未发布第13版)。有 19 相同的(内核未发布第13版)。有些计数器按每个运行队列统计是更有意义的,其它则 20 按每个调度域统计是更有意义的。 20 按每个调度域统计是更有意义的。注意,调度域(以及它们的附属信息)仅在开启 21 CONFIG_SMP的机器上是相关的和可用的 21 CONFIG_SMP的机器上是相关的和可用的。 22 22 23 在第14版schedstat中,每个被列出的CP 23 在第14版schedstat中,每个被列出的CPU至少会有一级域统计数据,且很可能有一个 24 以上的域。在这个实现中,域没有 24 以上的域。在这个实现中,域没有特别的名字,但是编号最高的域通常在机器上所有的 25 CPU上仲裁平衡,而domain0是最紧密聚 25 CPU上仲裁平衡,而domain0是最紧密聚焦的域,有时仅在一对CPU之间进行平衡。此时, 26 没有任何体系结构需要3层以上的域 26 没有任何体系结构需要3层以上的域。域统计数据中的第一个字段是一个位图,表明哪些 27 CPU受该域的影响。 27 CPU受该域的影响。 28 28 29 这些字段是计数器,而且只能递增 29 这些字段是计数器,而且只能递增。使用这些字段的程序将需要从基线观测开始,然后在 30 后续每一个观测中计算出计数器的 30 后续每一个观测中计算出计数器的变化。一个能以这种方式处理其中很多字段的perl脚本 31 可见 31 可见 32 32 33 http://eaglet.pdxhosts.com/rick/linux/sche 33 http://eaglet.pdxhosts.com/rick/linux/schedstat/ 34 34 35 请注意,任何这样的脚本都必须是 35 请注意,任何这样的脚本都必须是特定于版本的,改变版本的主要原因是输出格式的变化。 36 对于那些希望编写自己的脚本的人 36 对于那些希望编写自己的脚本的人,可以参考这里描述的各个字段。 37 37 38 CPU统计数据 38 CPU统计数据 39 ----------- 39 ----------- 40 cpu<N> 1 2 3 4 5 6 7 8 9 40 cpu<N> 1 2 3 4 5 6 7 8 9 41 41 42 第一个字段是sched_yield()的统计数据 42 第一个字段是sched_yield()的统计数据: 43 43 44 1) sched_yield()被调用了#次 44 1) sched_yield()被调用了#次 45 45 46 接下来的三个是schedule()的统计数据 46 接下来的三个是schedule()的统计数据: 47 47 48 2) 这个字段是一个过时的数组 48 2) 这个字段是一个过时的数组过期计数,在O(1)调度器中使用。为了ABI兼容性, 49 我们保留了它,但它总是被 49 我们保留了它,但它总是被设置为0。 50 3) schedule()被调用了#次 50 3) schedule()被调用了#次 51 4) 调用schedule()导致处理器变为 51 4) 调用schedule()导致处理器变为空闲了#次 52 52 53 接下来的两个是try_to_wake_up()的统计 53 接下来的两个是try_to_wake_up()的统计数据: 54 54 55 5) try_to_wake_up()被调用了#次 55 5) try_to_wake_up()被调用了#次 56 6) 调用try_to_wake_up()导致本地CPU 56 6) 调用try_to_wake_up()导致本地CPU被唤醒了#次 57 57 58 接下来的三个统计数据描述了调度 58 接下来的三个统计数据描述了调度延迟: 59 59 60 7) 本处理器运行任务的总时间 60 7) 本处理器运行任务的总时间,单位是纳秒 61 8) 本处理器任务等待运行的时 61 8) 本处理器任务等待运行的时间,单位是纳秒 62 9) 本CPU运行了#个时间片 62 9) 本CPU运行了#个时间片 63 63 64 域统计数据 64 域统计数据 65 ---------- 65 ---------- 66 66 67 对于每个被描述的CPU,和它相关的 67 对于每个被描述的CPU,和它相关的每一个调度域均会产生下面一行数据(注意,如果 68 CONFIG_SMP没有被定义,那么*没有*调 68 CONFIG_SMP没有被定义,那么*没有*调度域被使用,这些行不会出现在输出中)。 69 69 70 domain<N> <cpumask> 1 2 3 4 5 6 7 8 9 10 11 12 70 domain<N> <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 71 71 72 第一个字段是一个位掩码,表明该 72 第一个字段是一个位掩码,表明该域在操作哪些CPU。 73 73 74 接下来的24个字段是load_balance()函数 74 接下来的24个字段是load_balance()函数的各个统计数据,按空闲类型分组(空闲, 75 繁忙,新空闲): 75 繁忙,新空闲): 76 76 77 77 78 1) 当CPU空闲时,sched_balance_rq() !! 78 1) 当CPU空闲时,load_balance()在这个调度域中被调用了#次 79 2) 当CPU空闲时,sched_balance_rq() !! 79 2) 当CPU空闲时,load_balance()在这个调度域中被调用,但是发现负载无需 80 均衡#次 80 均衡#次 81 3) 当CPU空闲时,sched_balance_rq() !! 81 3) 当CPU空闲时,load_balance()在这个调度域中被调用,试图迁移1个或更多 82 任务且失败了#次 82 任务且失败了#次 83 4) 当CPU空闲时,sched_balance_rq() !! 83 4) 当CPU空闲时,load_balance()在这个调度域中被调用,发现不均衡(如果有) 84 #次 84 #次 85 5) 当CPU空闲时,pull_task()在这个 85 5) 当CPU空闲时,pull_task()在这个调度域中被调用#次 86 6) 当CPU空闲时,尽管目标任务 86 6) 当CPU空闲时,尽管目标任务是热缓存状态,pull_task()依然被调用#次 87 7) 当CPU空闲时,sched_balance_rq() !! 87 7) 当CPU空闲时,load_balance()在这个调度域中被调用,未能找到更繁忙的 88 队列#次 88 队列#次 89 8) 当CPU空闲时,在调度域中找 89 8) 当CPU空闲时,在调度域中找到了更繁忙的队列,但未找到更繁忙的调度组 90 #次 90 #次 91 9) 当CPU繁忙时,sched_balance_rq() !! 91 9) 当CPU繁忙时,load_balance()在这个调度域中被调用了#次 92 10) 当CPU繁忙时,sched_balance_rq() !! 92 10) 当CPU繁忙时,load_balance()在这个调度域中被调用,但是发现负载无需 93 均衡#次 93 均衡#次 94 11) 当CPU繁忙时,sched_balance_rq() !! 94 11) 当CPU繁忙时,load_balance()在这个调度域中被调用,试图迁移1个或更多 95 任务且失败了#次 95 任务且失败了#次 96 12) 当CPU繁忙时,sched_balance_rq() !! 96 12) 当CPU繁忙时,load_balance()在这个调度域中被调用,发现不均衡(如果有) 97 #次 97 #次 98 13) 当CPU繁忙时,pull_task()在这个 98 13) 当CPU繁忙时,pull_task()在这个调度域中被调用#次 99 14) 当CPU繁忙时,尽管目标任务 99 14) 当CPU繁忙时,尽管目标任务是热缓存状态,pull_task()依然被调用#次 100 15) 当CPU繁忙时,sched_balance_rq() !! 100 15) 当CPU繁忙时,load_balance()在这个调度域中被调用,未能找到更繁忙的 101 队列#次 101 队列#次 102 16) 当CPU繁忙时,在调度域中找 102 16) 当CPU繁忙时,在调度域中找到了更繁忙的队列,但未找到更繁忙的调度组 103 #次 103 #次 104 17) 当CPU新空闲时,sched_balance_rq( !! 104 17) 当CPU新空闲时,load_balance()在这个调度域中被调用了#次 105 18) 当CPU新空闲时,sched_balance_rq( !! 105 18) 当CPU新空闲时,load_balance()在这个调度域中被调用,但是发现负载无需 106 均衡#次 106 均衡#次 107 19) 当CPU新空闲时,sched_balance_rq( !! 107 19) 当CPU新空闲时,load_balance()在这个调度域中被调用,试图迁移1个或更多 108 任务且失败了#次 108 任务且失败了#次 109 20) 当CPU新空闲时,sched_balance_rq( !! 109 20) 当CPU新空闲时,load_balance()在这个调度域中被调用,发现不均衡(如果有) 110 #次 110 #次 111 21) 当CPU新空闲时,pull_task()在这 111 21) 当CPU新空闲时,pull_task()在这个调度域中被调用#次 112 22) 当CPU新空闲时,尽管目标任 112 22) 当CPU新空闲时,尽管目标任务是热缓存状态,pull_task()依然被调用#次 113 23) 当CPU新空闲时,sched_balance_rq( !! 113 23) 当CPU新空闲时,load_balance()在这个调度域中被调用,未能找到更繁忙的 114 队列#次 114 队列#次 115 24) 当CPU新空闲时,在调度域中 115 24) 当CPU新空闲时,在调度域中找到了更繁忙的队列,但未找到更繁忙的调度组 116 #次 116 #次 117 117 118 接下来的3个字段是active_load_balance() 118 接下来的3个字段是active_load_balance()函数的各个统计数据: 119 119 120 25) active_load_balance()被调用了#次 120 25) active_load_balance()被调用了#次 121 26) active_load_balance()被调用,试 121 26) active_load_balance()被调用,试图迁移1个或更多任务且失败了#次 122 27) active_load_balance()被调用,成 122 27) active_load_balance()被调用,成功迁移了#次任务 123 123 124 接下来的3个字段是sched_balance_exec() 124 接下来的3个字段是sched_balance_exec()函数的各个统计数据: 125 125 126 28) sbe_cnt不再被使用 126 28) sbe_cnt不再被使用 127 29) sbe_balanced不再被使用 127 29) sbe_balanced不再被使用 128 30) sbe_pushed不再被使用 128 30) sbe_pushed不再被使用 129 129 130 接下来的3个字段是sched_balance_fork() 130 接下来的3个字段是sched_balance_fork()函数的各个统计数据: 131 131 132 31) sbf_cnt不再被使用 132 31) sbf_cnt不再被使用 133 32) sbf_balanced不再被使用 133 32) sbf_balanced不再被使用 134 33) sbf_pushed不再被使用 134 33) sbf_pushed不再被使用 135 135 136 接下来的3个字段是try_to_wake_up()函 136 接下来的3个字段是try_to_wake_up()函数的各个统计数据: 137 137 138 34) 在这个调度域中调用try_to_wake 138 34) 在这个调度域中调用try_to_wake_up()唤醒任务时,任务在调度域中一个 139 和上次运行不同的新CPU上运 139 和上次运行不同的新CPU上运行了#次 140 35) 在这个调度域中调用try_to_wake 140 35) 在这个调度域中调用try_to_wake_up()唤醒任务时,任务被迁移到发生唤醒 141 的CPU次数为#,因为该任务在 141 的CPU次数为#,因为该任务在原CPU是冷缓存状态 142 36) 在这个调度域中调用try_to_wake 142 36) 在这个调度域中调用try_to_wake_up()唤醒任务时,引发被动负载均衡#次 143 143 144 /proc/<pid>/schedstat 144 /proc/<pid>/schedstat 145 --------------------- 145 --------------------- 146 schedstats还添加了一个新的/proc/<pid>/ 146 schedstats还添加了一个新的/proc/<pid>/schedstat文件,来提供一些进程级的 147 相同信息。这个文件中,有三个字 147 相同信息。这个文件中,有三个字段与该进程相关: 148 148 149 1) 在CPU上运行花费的时间(单位 149 1) 在CPU上运行花费的时间(单位是纳秒) 150 2) 在运行队列上等待的时间(单 150 2) 在运行队列上等待的时间(单位是纳秒) 151 3) 在CPU上运行了#个时间片 151 3) 在CPU上运行了#个时间片 152 152 153 可以很容易地编写一个程序,利用 153 可以很容易地编写一个程序,利用这些额外的字段来报告一个特定的进程或一组进程在 154 调度器策略下的表现如何。这样的 154 调度器策略下的表现如何。这样的程序的一个简单版本可在下面的链接找到 155 155 156 http://eaglet.pdxhosts.com/rick/linux/sche 156 http://eaglet.pdxhosts.com/rick/linux/schedstat/v12/latency.c
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.