ps で表示されるCPU使用率 = CPU時間 / 実行時間

LinuxCPU使用率の高いプロセスを探す時、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).
/* "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);
}