web-dev-qa-db-ja.com

/ proc / statを使用してLinuxのCPU使用率を正確に計算する

/ proc/statの統計を使用してCPU使用率を取得する方法に関する投稿とリファレンスが多数あります。ただし、それらのほとんどは、Linux 2.6に存在する残りのjiffie CPUカウント(iowait、irq、softirq)を無視して、7つ以上のCPU統計(ユーザー、ニース、システム、およびアイドル)のうち4つのみを使用します。

例として、 CPU使用率の決定 を参照してください。

私の質問はこれです:iowait/irq/softirq番号も最初の4つの番号(ユーザー/ニース/システム/アイドル)の1つでカウントされますか?言い換えれば、合計jiffieカウントは最初の4つの統計の合計に等しいですか?または、合計jiffieカウントは7つの統計すべての合計に等しいですか?後者が当てはまる場合、CPU使用率の式では、次のようにすべての数値を考慮する必要があります。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  long double a[7],b[7],loadavg;
  FILE *fp;

  for(;;)
  {
    fp = fopen("/proc/stat","r");
    fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&a[6]);
    fclose(fp);
    sleep(1);
    fp = fopen("/proc/stat","r");
    fscanf(fp,"%*s %Lf %Lf %Lf %Lf",&b[0],&b[1],&b[2],&b[3],&b[4],&b[5],&b[6]);
    fclose(fp);

    loadavg = ((b[0]+b[1]+b[2]+b[4]+b[5]+b[6]) - (a[0]+a[1]+a[2]+a[4]+a[5]+a[6]))
         / ((b[0]+b[1]+b[2]+b[3]+b[4]+b[5]+b[6]) - (a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]));
    printf("The current CPU utilization is : %Lf\n",loadavg);

  }

  return(0);
}
16
Stephen Schaub

Iowait/irq/softirqは最初の4つの数字の1つには数えられないと思います。詳細については、カーネルコードのirqtime_account_process_tickのコメントを参照してください。

Linuxカーネル4.1.1 の場合)

2815  * Tick demultiplexing follows the order
2816  * - pending hardirq update    <-- this is irq
2817  * - pending softirq update    <-- this is softirq
2818  * - user_time
2819  * - idle_time         <-- iowait is included in here, discuss below
2820  * - system time
2821  *   - check for guest_time
2822  *   - else account as system_time

アイドル時間の処理については、account_idle_time関数を参照してください。

2772 /*
2773  * Account for idle time.
2774  * @cputime: the cpu time spent in idle wait
2775  */
2776 void account_idle_time(cputime_t cputime)
2777 {
2778         u64 *cpustat = kcpustat_this_cpu->cpustat;
2779         struct rq *rq = this_rq();
2780
2781         if (atomic_read(&rq->nr_iowait) > 0)
2782                 cpustat[CPUTIME_IOWAIT] += (__force u64) cputime;
2783         else
2784                 cpustat[CPUTIME_IDLE] += (__force u64) cputime;
2785 }

CPUがアイドル状態で、IO保留中の場合は、CPUTIME_IOWAITで時間をカウントします。それ以外の場合は、CPUTIME_IDLEでカウントします。

結論として、irq/softirqのjiffiesは、実際にはいくつかのIRQまたはソフトIRQを処理していたため、CPUの「ビジー」としてカウントする必要があると思います。一方、「iowait」のjiffiesは、CPUの「アイドル」としてカウントする必要があります。これは、CPUが何かを実行しておらず、保留中のIOが発生するのを待っているためです。

10
Johnlcf

busybox から、その最高の魔法は次のとおりです。

static const char fmt[] ALIGN1 = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu";

    int ret;

    if (!fgets(line_buf, LINE_BUF_SIZE, fp) || line_buf[0] != 'c' /* not "cpu" */)
        return 0;
    ret = sscanf(line_buf, fmt,
            &p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle,
            &p_jif->iowait, &p_jif->irq, &p_jif->softirq,
            &p_jif->steal);
    if (ret >= 4) {
        p_jif->total = p_jif->usr + p_jif->nic + p_jif->sys + p_jif->idle
            + p_jif->iowait + p_jif->irq + p_jif->softirq + p_jif->steal;
        /* procps 2.x does not count iowait as busy time */
        p_jif->busy = p_jif->total - p_jif->idle - p_jif->iowait;
    }
1
Massimo