From a41b24a18cda433fe582bcfa5a6073fa237ac7db Mon Sep 17 00:00:00 2001 From: geekben Date: Mon, 6 Feb 2017 15:11:13 +0800 Subject: [PATCH] Add %wait to pidstat %wait: percentage of CPU spent by the task while waiting to run --- man/pidstat.1 | 5 ++++ pidstat.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-- pidstat.h | 3 +++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/man/pidstat.1 b/man/pidstat.1 index 756f88f..56920b0 100644 --- a/man/pidstat.1 +++ b/man/pidstat.1 @@ -400,6 +400,11 @@ Percentage of CPU spent by the task in virtual machine (running a virtual processor). .RE +.B %wait +.RS +Percentage of CPU spent by the task while waiting to run. +.RE + .B %CPU .RS Total percentage of CPU time used by the task. In an SMP environment, diff --git a/pidstat.c b/pidstat.c index 5412dde..6854fae 100644 --- a/pidstat.c +++ b/pidstat.c @@ -411,6 +411,63 @@ int read_proc_pid_stat(unsigned int pid, struct pid_stats *pst, return 0; } +/* + *************************************************************************** + * Read stats from /proc/#[/task/##]/schedstat. + * + * IN: + * @pid Process whose stats are to be read. + * @pst Pointer on structure where stats will be saved. + * @tgid If !=0, thread whose stats are to be read. + * + * OUT: + * @pst Pointer on structure where stats have been saved. + * @thread_nr Number of threads of the process. + * + * RETURNS: + * 0 if stats have been successfully read, and 1 otherwise. + *************************************************************************** + */ +int read_proc_pid_sched(unsigned int pid, struct pid_stats *pst, + unsigned int *thread_nr, unsigned int tgid) +{ + int fd, sz, rc; + char filename[128]; + static char buffer[1024 + 1]; + unsigned long long wtime; + + if (tgid) { + sprintf(filename, TASK_SCHED, tgid, pid); + } + else { + sprintf(filename, PID_SCHED, pid); + } + + if ((fd = open(filename, O_RDONLY)) < 0) + /* No such process */ + return 1; + + sz = read(fd, buffer, 1024); + close(fd); + if (sz <= 0) + return 1; + buffer[sz] = '\0'; + + rc = sscanf(buffer, + "%*u %llu %*d\n", + &wtime); + + if (rc < 1) + return 1; + + /* convert ns to jiffies */ + pst->wtime = wtime * HZ / 1000000000; + + pst->pid = pid; + pst->tgid = tgid; + return 0; +} + /* ***************************************************************************** * Read stats from /proc/#[/task/##]/status. @@ -728,6 +785,9 @@ int read_pid_stats(unsigned int pid, struct pid_stats *pst, if (read_proc_pid_stat(pid, pst, thread_nr, tgid)) return 1; + if (read_proc_pid_sched(pid, pst, thread_nr, tgid)) + return 1; + if (DISPLAY_CMDLINE(pidflag)) { if (read_proc_pid_cmdline(pid, pst, tgid)) return 1; @@ -1573,7 +1633,7 @@ int write_pid_task_cpu_stats(int prev, int curr, int dis, int disp_avg, if (dis) { PRINT_ID_HDR(prev_string, pidflag); - printf(" %%usr %%system %%guest %%CPU CPU Command\n"); + printf(" %%usr %%system %%guest %%wait %%CPU CPU Command\n"); } for (p = 0; p < pid_nr; p++) { @@ -1583,13 +1643,14 @@ int write_pid_task_cpu_stats(int prev, int curr, int dis, int disp_avg, continue; print_line_id(curr_string, pstc); - cprintf_pc(4, 7, 2, + cprintf_pc(5, 7, 2, (pstc->utime - pstc->gtime) < (pstp->utime - pstp->gtime) ? 0.0 : SP_VALUE_100(pstp->utime - pstp->gtime, pstc->utime - pstc->gtime, itv), SP_VALUE_100(pstp->stime, pstc->stime, itv), SP_VALUE_100(pstp->gtime, pstc->gtime, itv), + SP_VALUE_100(pstp->wtime, pstc->wtime, itv), /* User time already includes guest time */ IRIX_MODE_OFF(pidflag) ? SP_VALUE_100(pstp->utime + pstp->stime, diff --git a/pidstat.h b/pidstat.h index f58ee0c..61d46fb 100644 --- a/pidstat.h +++ b/pidstat.h @@ -100,9 +100,11 @@ #define PID_CMDLINE "/proc/%u/cmdline" #define PID_SMAP "/proc/%u/smaps" #define PID_FD "/proc/%u/fd" +#define PID_SCHED "/proc/%u/schedstat" #define PROC_TASK "/proc/%u/task" #define TASK_STAT "/proc/%u/task/%u/stat" +#define TASK_SCHED "/proc/%u/task/%u/schedstat" #define TASK_STATUS "/proc/%u/task/%u/status" #define TASK_IO "/proc/%u/task/%u/io" #define TASK_CMDLINE "/proc/%u/task/%u/cmdline" @@ -176,6 +178,7 @@ struct pid_stats { long long cstime __attribute__ ((packed)); unsigned long long gtime __attribute__ ((packed)); long long cgtime __attribute__ ((packed)); + unsigned long long wtime __attribute__ ((packed)); unsigned long long vsz __attribute__ ((packed)); unsigned long long rss __attribute__ ((packed)); unsigned long nvcsw __attribute__ ((packed)); -- 2.40.0