.. SPDX-License-Identifier: GPL-2.0 .. include:: ../disclaimer-zh_CN.rst :Original: Documentation/scheduler/sched-stats.rst :翻译: å”艺舟 Tang Yizhou <tangyeechou@gmail.com> ============== è°ƒåº¦å™¨ç»Ÿè®¡æ•°æ® ============== 第15版schedstats去掉了sched_yield的一些计数器:yld_exp_empty,yld_act_empty å’Œyld_both_empty。在其它方é¢å’Œç¬¬14版完全相åŒã€‚ 第14版schedstats包括对sched_domains(译注:调度域)的支æŒï¼Œè¯¥ç‰¹æ€§è¿›å…¥å†…æ ¸ 主线2.6.20,ä¸è¿‡è¿™ä¸€ç‰ˆschedstats与2.6.13-2.6.19å†…æ ¸çš„ç‰ˆæœ¬12的统计数æ®æ˜¯å®Œå…¨ 相åŒçš„ï¼ˆå†…æ ¸æœªå‘布第13版)。有些计数器按æ¯ä¸ªè¿è¡Œé˜Ÿåˆ—统计是更有æ„义的,其它则 按æ¯ä¸ªè°ƒåº¦åŸŸç»Ÿè®¡æ˜¯æ›´æœ‰æ„义的。注æ„,调度域(以åŠå®ƒä»¬çš„附属信æ¯ï¼‰ä»…åœ¨å¼€å¯ CONFIG_SMP的机器上是相关的和å¯ç”¨çš„。 在第14版schedstatä¸ï¼Œæ¯ä¸ªè¢«åˆ—出的CPU至少会有一级域统计数æ®ï¼Œä¸”很å¯èƒ½æœ‰ä¸€ä¸ª 以上的域。在这个实现ä¸ï¼ŒåŸŸæ²¡æœ‰ç‰¹åˆ«çš„åå—,但是编å·æœ€é«˜çš„域通常在机器上所有的 CPU上仲è£å¹³è¡¡ï¼Œè€Œdomain0是最紧密èšç„¦çš„域,有时仅在一对CPU之间进行平衡。æ¤æ—¶ï¼Œ 没有任何体系结构需è¦3层以上的域。域统计数æ®ä¸çš„第一个å—段是一个ä½å›¾ï¼Œè¡¨æ˜Žå“ªäº› CPUå—该域的影å“。 这些å—段是计数器,而且åªèƒ½é€’增。使用这些å—段的程åºå°†éœ€è¦ä»ŽåŸºçº¿è§‚测开始,然åŽåœ¨ åŽç»æ¯ä¸€ä¸ªè§‚测ä¸è®¡ç®—出计数器的å˜åŒ–。一个能以这ç§æ–¹å¼å¤„ç†å…¶ä¸å¾ˆå¤šå—段的perl脚本 å¯è§ http://eaglet.pdxhosts.com/rick/linux/schedstat/ 请注æ„ï¼Œä»»ä½•è¿™æ ·çš„è„šæœ¬éƒ½å¿…é¡»æ˜¯ç‰¹å®šäºŽç‰ˆæœ¬çš„ï¼Œæ”¹å˜ç‰ˆæœ¬çš„主è¦åŽŸå› æ˜¯è¾“å‡ºæ ¼å¼çš„å˜åŒ–。 对于那些希望编写自己的脚本的人,å¯ä»¥å‚考这里æè¿°çš„å„个å—段。 CPUç»Ÿè®¡æ•°æ® ----------- cpu<N> 1 2 3 4 5 6 7 8 9 第一个å—段是sched_yield()的统计数æ®ï¼š 1) sched_yield()被调用了#次 接下æ¥çš„三个是schedule()的统计数æ®ï¼š 2) 这个å—段是一个过时的数组过期计数,在O(1)调度器ä¸ä½¿ç”¨ã€‚为了ABI兼容性, 我们ä¿ç•™äº†å®ƒï¼Œä½†å®ƒæ€»æ˜¯è¢«è®¾ç½®ä¸º0。 3) schedule()被调用了#次 4) 调用schedule()导致处ç†å™¨å˜ä¸ºç©ºé—²äº†#次 接下æ¥çš„两个是try_to_wake_up()的统计数æ®ï¼š 5) try_to_wake_up()被调用了#次 6) 调用try_to_wake_up()导致本地CPU被唤醒了#次 接下æ¥çš„三个统计数æ®æ述了调度延迟: 7) 本处ç†å™¨è¿è¡Œä»»åŠ¡çš„总时间,å•ä½æ˜¯çº³ç§’ 8) 本处ç†å™¨ä»»åŠ¡ç‰å¾…è¿è¡Œçš„时间,å•ä½æ˜¯çº³ç§’ 9) 本CPUè¿è¡Œäº†#个时间片 åŸŸç»Ÿè®¡æ•°æ® ---------- 对于æ¯ä¸ªè¢«æè¿°çš„CPU,和它相关的æ¯ä¸€ä¸ªè°ƒåº¦åŸŸå‡ä¼šäº§ç”Ÿä¸‹é¢ä¸€è¡Œæ•°æ®ï¼ˆæ³¨æ„,如果 CONFIG_SMP没有被定义,那么*没有*调度域被使用,这些行ä¸ä¼šå‡ºçŽ°åœ¨è¾“出ä¸ï¼‰ã€‚ 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 第一个å—段是一个ä½æŽ©ç ,表明该域在æ“作哪些CPU。 接下æ¥çš„24个å—段是load_balance()函数的å„个统计数æ®ï¼ŒæŒ‰ç©ºé—²ç±»åž‹åˆ†ç»„(空闲, ç¹å¿™ï¼Œæ–°ç©ºé—²ï¼‰ï¼š 1) 当CPU空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨äº†#次 2) 当CPU空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œä½†æ˜¯å‘çŽ°è´Ÿè½½æ— éœ€ å‡è¡¡#次 3) 当CPU空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œè¯•å›¾è¿ç§»1个或更多 任务且失败了#次 4) 当CPU空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œå‘现ä¸å‡è¡¡ï¼ˆå¦‚果有) #次 5) 当CPU空闲时,pull_task()在这个调度域ä¸è¢«è°ƒç”¨#次 6) 当CPUç©ºé—²æ—¶ï¼Œå°½ç®¡ç›®æ ‡ä»»åŠ¡æ˜¯çƒç¼“å˜çŠ¶æ€ï¼Œpull_task()ä¾ç„¶è¢«è°ƒç”¨#次 7) 当CPU空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œæœªèƒ½æ‰¾åˆ°æ›´ç¹å¿™çš„ 队列#次 8) 当CPU空闲时,在调度域ä¸æ‰¾åˆ°äº†æ›´ç¹å¿™çš„队列,但未找到更ç¹å¿™çš„调度组 #次 9) 当CPUç¹å¿™æ—¶ï¼Œload_balance()在这个调度域ä¸è¢«è°ƒç”¨äº†#次 10) 当CPUç¹å¿™æ—¶ï¼Œload_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œä½†æ˜¯å‘çŽ°è´Ÿè½½æ— éœ€ å‡è¡¡#次 11) 当CPUç¹å¿™æ—¶ï¼Œload_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œè¯•å›¾è¿ç§»1个或更多 任务且失败了#次 12) 当CPUç¹å¿™æ—¶ï¼Œload_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œå‘现ä¸å‡è¡¡ï¼ˆå¦‚果有) #次 13) 当CPUç¹å¿™æ—¶ï¼Œpull_task()在这个调度域ä¸è¢«è°ƒç”¨#次 14) 当CPUç¹å¿™æ—¶ï¼Œå°½ç®¡ç›®æ ‡ä»»åŠ¡æ˜¯çƒç¼“å˜çŠ¶æ€ï¼Œpull_task()ä¾ç„¶è¢«è°ƒç”¨#次 15) 当CPUç¹å¿™æ—¶ï¼Œload_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œæœªèƒ½æ‰¾åˆ°æ›´ç¹å¿™çš„ 队列#次 16) 当CPUç¹å¿™æ—¶ï¼Œåœ¨è°ƒåº¦åŸŸä¸æ‰¾åˆ°äº†æ›´ç¹å¿™çš„队列,但未找到更ç¹å¿™çš„调度组 #次 17) 当CPU新空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨äº†#次 18) 当CPU新空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œä½†æ˜¯å‘çŽ°è´Ÿè½½æ— éœ€ å‡è¡¡#次 19) 当CPU新空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œè¯•å›¾è¿ç§»1个或更多 任务且失败了#次 20) 当CPU新空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œå‘现ä¸å‡è¡¡ï¼ˆå¦‚果有) #次 21) 当CPU新空闲时,pull_task()在这个调度域ä¸è¢«è°ƒç”¨#次 22) 当CPUæ–°ç©ºé—²æ—¶ï¼Œå°½ç®¡ç›®æ ‡ä»»åŠ¡æ˜¯çƒç¼“å˜çŠ¶æ€ï¼Œpull_task()ä¾ç„¶è¢«è°ƒç”¨#次 23) 当CPU新空闲时,load_balance()在这个调度域ä¸è¢«è°ƒç”¨ï¼Œæœªèƒ½æ‰¾åˆ°æ›´ç¹å¿™çš„ 队列#次 24) 当CPU新空闲时,在调度域ä¸æ‰¾åˆ°äº†æ›´ç¹å¿™çš„队列,但未找到更ç¹å¿™çš„调度组 #次 接下æ¥çš„3个å—段是active_load_balance()函数的å„个统计数æ®ï¼š 25) active_load_balance()被调用了#次 26) active_load_balance()被调用,试图è¿ç§»1个或更多任务且失败了#次 27) active_load_balance()被调用,æˆåŠŸè¿ç§»äº†#次任务 接下æ¥çš„3个å—段是sched_balance_exec()函数的å„个统计数æ®ï¼š 28) sbe_cntä¸å†è¢«ä½¿ç”¨ 29) sbe_balancedä¸å†è¢«ä½¿ç”¨ 30) sbe_pushedä¸å†è¢«ä½¿ç”¨ 接下æ¥çš„3个å—段是sched_balance_fork()函数的å„个统计数æ®ï¼š 31) sbf_cntä¸å†è¢«ä½¿ç”¨ 32) sbf_balancedä¸å†è¢«ä½¿ç”¨ 33) sbf_pushedä¸å†è¢«ä½¿ç”¨ 接下æ¥çš„3个å—段是try_to_wake_up()函数的å„个统计数æ®ï¼š 34) 在这个调度域ä¸è°ƒç”¨try_to_wake_up()唤醒任务时,任务在调度域ä¸ä¸€ä¸ª 和上次è¿è¡Œä¸åŒçš„æ–°CPU上è¿è¡Œäº†#次 35) 在这个调度域ä¸è°ƒç”¨try_to_wake_up()唤醒任务时,任务被è¿ç§»åˆ°å‘生唤醒 çš„CPU次数为#ï¼Œå› ä¸ºè¯¥ä»»åŠ¡åœ¨åŽŸCPU是冷缓å˜çŠ¶æ€ 36) 在这个调度域ä¸è°ƒç”¨try_to_wake_up()唤醒任务时,引å‘被动负载å‡è¡¡#次 /proc/<pid>/schedstat --------------------- schedstatsè¿˜æ·»åŠ äº†ä¸€ä¸ªæ–°çš„/proc/<pid>/schedstat文件,æ¥æ供一些进程级的 相åŒä¿¡æ¯ã€‚这个文件ä¸ï¼Œæœ‰ä¸‰ä¸ªå—段与该进程相关: 1) 在CPU上è¿è¡ŒèŠ±è´¹çš„时间(å•ä½æ˜¯çº³ç§’) 2) 在è¿è¡Œé˜Ÿåˆ—上ç‰å¾…的时间(å•ä½æ˜¯çº³ç§’) 3) 在CPU上è¿è¡Œäº†#个时间片 å¯ä»¥å¾ˆå®¹æ˜“地编写一个程åºï¼Œåˆ©ç”¨è¿™äº›é¢å¤–çš„å—段æ¥æŠ¥å‘Šä¸€ä¸ªç‰¹å®šçš„进程或一组进程在 调度器ç–ç•¥ä¸‹çš„è¡¨çŽ°å¦‚ä½•ã€‚è¿™æ ·çš„ç¨‹åºçš„一个简å•ç‰ˆæœ¬å¯åœ¨ä¸‹é¢çš„链接找到 http://eaglet.pdxhosts.com/rick/linux/schedstat/v12/latency.c