スレッドのCPU利用率の計算
Rev.17を表示中。最新版はこちら。
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 = delta」としないのは、1tick内にスレッドが必ずスケジュールされるわけではないため、5/8エージングで過去のCPU使用量も反映させつつ現在の使用量を求めることで値を平滑化するため。
(*1) ここでtickはスケジューラの周期処理sched_tick_thread()が動作した回数
CPU利用率の算出
psコマンドで表示するCPU利用率(%)に変換するためにはcpu_usageを元に以下の計算を行なう。(小数点を含めて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; (*2)
basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5; (*3)
(*2) CPU使用量をスケジューラ周期処理のタイマ値(sched_tick_interval)で割ることで単位時間あたりのCPU使用量を求める。また、%を0〜1000の値にするため、TH_USAGE_SCALEを乗じている。
(*3) (*2)で求めた単位時間あたりのCPU使用量を「CPUを100%使用した場合の単位時間あたりのCPU使用量」で割ることで%を算出する。式中でbasic_info->cpu_usage に 3/5を掛けているが3/5の意味は以下の通り。
「CPUを100%使用した場合の単位時間あたりのCPU使用量」はcpu_usageと同じく5/8 エージングをさせて
(5/8) + (5/8)**2 + (5/8)**3 + ...
で表すことができる。コードで書くと以下。
while (1) {
$full_usage += 1;
$full_usage = $full_usage * 5/8; #Ageing
}
これは 初項 a: 5/8、公比 r: 5/8の無限等比級数でその和はa/(1-r)となる。つまり(5/8)/(1-5/8)⇒(5/3)となる。この値でcpu_usageを割るので。 basic_info->cpu_usage * (3/5)となる。