スレッドのCPU利用率の計算
Rev.13を表示中。最新版はこちら。
CPU使用量
スレッドを示すthread構造体にそのスレッドが、どれだけCPUを使用したかを示すcpu_usageというものがある(スレッド参照)。この値はCPU利用率(%)ではなくCPU使用時間をベースにした値で、スケジューラの周期処理からupdate_priority()が呼ばれて定期的に更新される。
具体的にはCPU使用時間(System+User時間)を足し、前回の更新からの経過tick数(*1)に応じ エージング(1tickにつき5/8)して算出される。式は以下のとおり。
cpu_usage = (cpu_usage + delta)*(5/8)**(前回の更新からの経過tick数)
delta:前回の更新以降使用したCPU時間
単純に「cpu_usage = CPU時間」としないのは、1tick内にスレッドが必ずスケジュールされるわけではないため、過去のCPU使用量も反映させて現在の使用量を求めることで値を平滑化するため。
(*1) ここでtickはスケジューラの周期処理sched_tick_thread()が動作した回数
CPU利用率の算出
psコマンドで表示するCPU利用率(%)に変換するために以下の計算を行なう。(実際には小数点を含めて0.0〜100.0%なので0〜1000の値になる。)以下のTH_USAGE_SCALEは1000。
basic_info->cpu_usage = ((uint64_t)thread->cpu_usage
* TH_USAGE_SCALE) / sched_tick_interval;
basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5;
if (basic_info->cpu_usage > TH_USAGE_SCALE)
basic_info->cpu_usage
= TH_USAGE_SCALE;
最初の計算で単位時間あたりのCPU使用量を求め、二つめの式で
cpu_usageが*3/5となっているのは
単位時間あたりCPUをフルに使用した場合のCPU使用量は
(5/8) + (5/8)**2 + (5/8)**3 + ...
これは 初項 a: 5/8、公比 r: 5/8の無限等比級数でその和はa/(1-r)となる。
つまり(5/8)/(1-5/8)となる。
この値でcpu_usageを割っている。
cpu_usage/((5/8)/(1-5/8)) ⇒ cpu_usage * (3/5)
となる。