From 2c86c4984a15c9ab912402838c6651f466a3d2ed Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Tue, 27 Dec 2016 08:08:08 -0600 Subject: [PATCH] library : standardized new category calculations This commit arose out of the discussion (and research) surrounding the issue cited below. It is an attempt to consolidate and standardize the calculation of jiffies categories (e.g. 'idle', 'busy', etc.) once & for all. Also included is the enum STAT_TIC_NUM_CONTRIBUTORS in case anyone, in the future, decides to calculate usage based upon elapsed time * Hz (like top does in process level %CPU stats). In such an event, a total number of CPUs or NUMA Nodes would be needed for proper scaling. Reference(s): https://gitlab.com/procps-ng/procps/issues/48 Signed-off-by: Jim Warner --- proc/stat.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++- proc/stat.h | 13 +++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/proc/stat.c b/proc/stat.c index 9eccb133..452860f6 100644 --- a/proc/stat.c +++ b/proc/stat.c @@ -57,6 +57,7 @@ struct stat_jifs { unsigned long long user, nice, system, idle, iowait, irq, sirq, stolen, guest, gnice; + unsigned long long xtot, xbsy, xidl, xusr, xsys; }; struct stat_data { @@ -76,6 +77,7 @@ struct hist_sys { struct hist_tic { int id; int numa_node; + int count; struct stat_jifs new; struct stat_jifs old; }; @@ -159,6 +161,7 @@ setDECL(extra) { (void)R; (void)S; (void)T; } setDECL(TIC_ID) { (void)S; R->result.s_int = T->id; } setDECL(TIC_NUMA_NODE) { (void)S; R->result.s_int = T->numa_node; } +setDECL(TIC_NUM_CONTRIBUTORS) { (void)S; R->result.s_int = T->count; } TIC_set(TIC_USER, ull_int, user) TIC_set(TIC_NICE, ull_int, nice) @@ -171,6 +174,12 @@ TIC_set(TIC_STOLEN, ull_int, stolen) TIC_set(TIC_GUEST, ull_int, guest) TIC_set(TIC_GUEST_NICE, ull_int, gnice) +TIC_set(TIC_SUM_TOTAL, ull_int, xtot) +TIC_set(TIC_SUM_BUSY, ull_int, xbsy) +TIC_set(TIC_SUM_IDLE, ull_int, xidl) +TIC_set(TIC_SUM_USER, ull_int, xusr) +TIC_set(TIC_SUM_SYSTEM, ull_int, xsys) + TICsetH(TIC_DELTA_USER, sl_int, user) TICsetH(TIC_DELTA_NICE, sl_int, nice) TICsetH(TIC_DELTA_SYSTEM, sl_int, system) @@ -182,6 +191,12 @@ TICsetH(TIC_DELTA_STOLEN, sl_int, stolen) TICsetH(TIC_DELTA_GUEST, sl_int, guest) TICsetH(TIC_DELTA_GUEST_NICE, sl_int, gnice) +TICsetH(TIC_DELTA_SUM_TOTAL, sl_int, xtot) +TICsetH(TIC_DELTA_SUM_BUSY, sl_int, xbsy) +TICsetH(TIC_DELTA_SUM_IDLE, sl_int, xidl) +TICsetH(TIC_DELTA_SUM_USER, sl_int, xusr) +TICsetH(TIC_DELTA_SUM_SYSTEM, sl_int, xsys) + SYS_set(SYS_CTX_SWITCHES, ul_int, ctxt) SYS_set(SYS_INTERRUPTS, ul_int, intr) SYS_set(SYS_PROC_BLOCKED, ul_int, procs_blocked) @@ -276,6 +291,7 @@ static struct { { RS(TIC_ID), QS(s_int), TS(s_int) }, { RS(TIC_NUMA_NODE), QS(s_int), TS(s_int) }, + { RS(TIC_NUM_CONTRIBUTORS), QS(s_int), TS(s_int) }, { RS(TIC_USER), QS(ull_int), TS(ull_int) }, { RS(TIC_NICE), QS(ull_int), TS(ull_int) }, { RS(TIC_SYSTEM), QS(ull_int), TS(ull_int) }, @@ -287,6 +303,12 @@ static struct { { RS(TIC_GUEST), QS(ull_int), TS(ull_int) }, { RS(TIC_GUEST_NICE), QS(ull_int), TS(ull_int) }, + { RS(TIC_SUM_TOTAL), QS(ull_int), TS(ull_int) }, + { RS(TIC_SUM_BUSY), QS(ull_int), TS(ull_int) }, + { RS(TIC_SUM_IDLE), QS(ull_int), TS(ull_int) }, + { RS(TIC_SUM_USER), QS(ull_int), TS(ull_int) }, + { RS(TIC_SUM_SYSTEM), QS(ull_int), TS(ull_int) }, + { RS(TIC_DELTA_USER), QS(sl_int), TS(sl_int) }, { RS(TIC_DELTA_NICE), QS(sl_int), TS(sl_int) }, { RS(TIC_DELTA_SYSTEM), QS(sl_int), TS(sl_int) }, @@ -298,6 +320,12 @@ static struct { { RS(TIC_DELTA_GUEST), QS(sl_int), TS(sl_int) }, { RS(TIC_DELTA_GUEST_NICE), QS(sl_int), TS(sl_int) }, + { RS(TIC_DELTA_SUM_TOTAL), QS(sl_int), TS(sl_int) }, + { RS(TIC_DELTA_SUM_BUSY), QS(sl_int), TS(sl_int) }, + { RS(TIC_DELTA_SUM_IDLE), QS(sl_int), TS(sl_int) }, + { RS(TIC_DELTA_SUM_USER), QS(sl_int), TS(sl_int) }, + { RS(TIC_DELTA_SUM_SYSTEM), QS(sl_int), TS(sl_int) }, + { RS(SYS_CTX_SWITCHES), QS(ul_int), TS(ul_int) }, { RS(SYS_INTERRUPTS), QS(ul_int), TS(ul_int) }, { RS(SYS_PROC_BLOCKED), QS(ul_int), TS(ul_int) }, @@ -385,6 +413,33 @@ static inline void stat_cleanup_stacks_all ( } // end: stat_cleanup_stacks_all +static inline int stat_derive_unique ( + struct hist_tic *this) +{ + /* note: we exclude guest tics from xtot since ... + 'user' already includes 'guest' + 'nice' already includes 'gnice' + ( see: ./kernel/sched/cputime.c, account_guest_time ) */ + this->new.xtot + = this->new.user + + this->new.nice + + this->new.system + + this->new.idle + + this->new.iowait + + this->new.irq + + this->new.sirq + + this->new.stolen; + this->new.xusr = this->new.user + this->new.nice; + /* this stolen guy is one i'm not sure of yet, but it's documented as: + "the time spent in other operating systems + when running in a virtualized environment" + so it would seem to apply to an 'involuntary wait' for a guest OS */ + this->new.xidl = this->new.idle + this->new.iowait + this->new.stolen; + this->new.xbsy = this->new.xtot - this->new.xidl; + this->new.xsys = this->new.xbsy - this->new.xusr; +} // end: stat_derive_unique + + static void stat_extents_free_all ( struct ext_support *this) { @@ -490,8 +545,15 @@ static int stat_make_numa_hist ( nod_ptr->new.guest += cpu_ptr->new.guest; nod_ptr->old.guest += cpu_ptr->old.guest; nod_ptr->new.gnice += cpu_ptr->new.gnice; nod_ptr->old.gnice += cpu_ptr->old.gnice; + nod_ptr->new.xtot += cpu_ptr->new.xtot; nod_ptr->old.xtot += cpu_ptr->old.xtot; + nod_ptr->new.xbsy += cpu_ptr->new.xbsy; nod_ptr->old.xbsy += cpu_ptr->old.xbsy; + nod_ptr->new.xidl += cpu_ptr->new.xidl; nod_ptr->old.xidl += cpu_ptr->old.xidl; + nod_ptr->new.xusr += cpu_ptr->new.xusr; nod_ptr->old.xusr += cpu_ptr->old.xusr; + nod_ptr->new.xsys += cpu_ptr->new.xsys; nod_ptr->old.xsys += cpu_ptr->old.xsys; + cpu_ptr->numa_node = node; nod_ptr->id = node; + nod_ptr->count++; ; } } info->nodes.hist.n_inuse = info->nodes.total; @@ -554,6 +616,7 @@ static int stat_read_failed ( , &sum_ptr->new.sirq, &sum_ptr->new.stolen , &sum_ptr->new.guest, &sum_ptr->new.gnice)) return -1; + stat_derive_unique(sum_ptr); // let's not distort the deltas the first time thru ... if (!info->stat_was_read) memcpy(&sum_ptr->old, &sum_ptr->new, sizeof(struct stat_jifs)); @@ -568,6 +631,7 @@ reap_em_again: memcpy(&cpu_ptr->old, &cpu_ptr->new, sizeof(struct stat_jifs)); // next can be overridden under 'stat_make_numa_hist' cpu_ptr->numa_node = STAT_NODE_INVALID; + cpu_ptr->count = 1; if (8 > (rc = sscanf(bp, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu" , &cpu_ptr->id @@ -580,6 +644,7 @@ reap_em_again: cpu_ptr->id = id_sav; break; // we must tolerate cpus taken offline } + stat_derive_unique(cpu_ptr); // let's not distort the deltas the first time thru ... if (!info->stat_was_read) memcpy(&cpu_ptr->old, &cpu_ptr->new, sizeof(struct stat_jifs)); @@ -595,7 +660,7 @@ reap_em_again: goto reap_em_again; } - info->cpus.total = info->cpus.hist.n_inuse = i; + info->cpus.total = info->cpus.hist.n_inuse = sum_ptr->count = i; // remember sys_hist stuff from last time around memcpy(&info->sys_hist.old, &info->sys_hist.new, sizeof(struct stat_data)); diff --git a/proc/stat.h b/proc/stat.h index e89c64dd..6151e282 100644 --- a/proc/stat.h +++ b/proc/stat.h @@ -29,6 +29,7 @@ enum stat_item { STAT_TIC_ID, // s_int STAT_TIC_NUMA_NODE, // s_int + STAT_TIC_NUM_CONTRIBUTORS, // s_int STAT_TIC_USER, // ull_int STAT_TIC_NICE, // ull_int STAT_TIC_SYSTEM, // ull_int @@ -40,6 +41,12 @@ enum stat_item { STAT_TIC_GUEST, // ull_int STAT_TIC_GUEST_NICE, // ull_int + STAT_TIC_SUM_TOTAL, // ull_int + STAT_TIC_SUM_BUSY, // ull_int + STAT_TIC_SUM_IDLE, // ull_int + STAT_TIC_SUM_USER, // ull_int + STAT_TIC_SUM_SYSTEM, // ull_int + STAT_TIC_DELTA_USER, // sl_int STAT_TIC_DELTA_NICE, // sl_int STAT_TIC_DELTA_SYSTEM, // sl_int @@ -51,6 +58,12 @@ enum stat_item { STAT_TIC_DELTA_GUEST, // sl_int STAT_TIC_DELTA_GUEST_NICE, // sl_int + STAT_TIC_DELTA_SUM_TOTAL, // sl_int + STAT_TIC_DELTA_SUM_BUSY, // sl_int + STAT_TIC_DELTA_SUM_IDLE, // sl_int + STAT_TIC_DELTA_SUM_USER, // sl_int + STAT_TIC_DELTA_SUM_SYSTEM, // sl_int + STAT_SYS_CTX_SWITCHES, // ul_int STAT_SYS_INTERRUPTS, // ul_int STAT_SYS_PROC_BLOCKED, // ul_int