Linux でCPU使用率の高いプロセスを探す時、ps で表示されるCPU使用率は累計値になるので、top を使うけど、ps で表示されるCPU使用率の算出式が気になったので、調べてみた。
- 算出式
CPU使用率 = ( プロセスが使用したCPU時間 / プロセスの実行時間 ) * 100
- man より
$ ps -V procps version 3.2.8 $ man ps %cpu %CPU cpu utilization of the process in "##.#" format. Currently, it is the CPU time used divided by the time the process has been running (cputime/realtime ratio), expressed as a percentage. It will not add up to 100% unless you are lucky. (alias pcpu).
- ソースコード(procps-3.2.8/ps/output.c)より
/* "Processor utilisation for scheduling." --- we use %cpu w/o fraction */ static int pr_c(char *restrict const outbuf, const proc_t *restrict const pp){ unsigned long long total_time; /* jiffies used by this process */ unsigned pcpu = 0; /* scaled %cpu, 99 means 99% */ unsigned long long seconds; /* seconds of process life */ total_time = pp->utime + pp->stime; ★ if(include_dead_children) total_time += (pp->cutime + pp->cstime); seconds = seconds_since_boot - pp->start_time / Hertz; ★ if(seconds) pcpu = (total_time * 100ULL / Hertz) / seconds; ★ if (pcpu > 99U) pcpu = 99U; return snprintf(outbuf, COLWID, "%2u", pcpu); } /* normal %CPU in ##.# format. */ static int pr_pcpu(char *restrict const outbuf, const proc_t *restrict const pp){ unsigned long long total_time; /* jiffies used by this process */ unsigned pcpu = 0; /* scaled %cpu, 999 means 99.9% */ unsigned long long seconds; /* seconds of process life */ total_time = pp->utime + pp->stime; ★ if(include_dead_children) total_time += (pp->cutime + pp->cstime); seconds = seconds_since_boot - pp->start_time / Hertz; ★ if(seconds) pcpu = (total_time * 1000ULL / Hertz) / seconds; ★ if (pcpu > 999U) return snprintf(outbuf, COLWID, "%u", pcpu/10U); return snprintf(outbuf, COLWID, "%u.%u", pcpu/10U, pcpu%10U); } /* this is a "per-mill" format, like %cpu with no decimal point */ static int pr_cp(char *restrict const outbuf, const proc_t *restrict const pp){ unsigned long long total_time; /* jiffies used by this process */ unsigned pcpu = 0; /* scaled %cpu, 999 means 99.9% */ unsigned long long seconds; /* seconds of process life */ total_time = pp->utime + pp->stime; ★ if(include_dead_children) total_time += (pp->cutime + pp->cstime); seconds = seconds_since_boot - pp->start_time / Hertz ; ★ if(seconds) pcpu = (total_time * 1000ULL / Hertz) / seconds; ★ if (pcpu > 999U) pcpu = 999U; return snprintf(outbuf, COLWID, "%3u", pcpu); }