From: Sebastien Godard Date: Mon, 15 Aug 2011 14:00:05 +0000 (+0200) Subject: Option "-P ON" added to mpstat. X-Git-Tag: v10.0.2~3 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9c9a505b9cfa084b675456f9856e0e3854652dae;p=sysstat Option "-P ON" added to mpstat. This option tells mpstat to display statistics for online processors only. mpstat manual page updated. On 06/30/2011 06:41 AM, Ananth N Mavinakayanahalli wrote: a. Consistency with output of top and /proc/cpuinfo, both of which won't display information of offlined CPUs. b. On POWER7 for instance, with SMT, when SMT is turned off, 3 of the 4 CPUs are off-lined. Someone using just mpstat will have no idea that he has just 1 CPU underneath while mpstat says he has 4, without an indication of which ones are usable and which ones are not. I think, at the least, the -P switch should be educated with a new option that displays only online CPU information, if there is a hard requirement to preserve existing functionality. --- diff --git a/CHANGES b/CHANGES index 9532368..7551cc5 100644 --- a/CHANGES +++ b/CHANGES @@ -5,10 +5,12 @@ xxxx/xx/xx: Version 10.0.2 - Sebastien Godard (sysstat orange.fr) Its design is still not generic anyway. * Option -T added to sadf: This option tells sadf to display timestamps in seconds since the epoch (when applicable). + * Option "-P ON" added to mpstat. This option tells mpstat + to display stats only for online CPU. * [Jeroen Roovers]: Automate translation files handling in Makefile.in. * DTD and XSD documents updated. - * sadf manual page updated. + * sadf and mpstat manual pages updated. * pidstat manual page updated: Added description of field %MEM displayed by pidstat -r. * Various cosmetic changes (sar.c, sadf.c). diff --git a/man/mpstat.1 b/man/mpstat.1 index 1d0527d..1f1fdb3 100644 --- a/man/mpstat.1 +++ b/man/mpstat.1 @@ -1,10 +1,10 @@ -.TH MPSTAT 1 "JANUARY 2010" Linux "Linux User's Manual" -*- nroff -*- +.TH MPSTAT 1 "AUGUST 2011" Linux "Linux User's Manual" -*- nroff -*- .SH NAME mpstat \- Report processors related statistics. .SH SYNOPSIS .B mpstat [ -A ] [ -I { SUM | CPU | SCPU | ALL } ] [ -u ] [ -P { .I cpu -.B [,...] | ALL } ] [ -V ] [ +.B [,...] | ON | ALL } ] [ -V ] [ .I interval .B [ .I count @@ -88,11 +88,14 @@ keyword is equivalent to specifying all the keywords above and therefore all the interrupts statistics are displayed. .RE .RE -.IP "-P { cpu [,...] | ALL }" +.IP "-P { cpu [,...] | ON | ALL }" Indicate the processor number for which statistics are to be reported. .I cpu is the processor number. Note that processor 0 is the first processor. The +.B ON +keyword indicates that statistics are to be reported for every +online processor, whereas the .B ALL keyword indicates that statistics are to be reported for all processors. .IP -u diff --git a/mpstat.c b/mpstat.c index 118036a..a8669dc 100644 --- a/mpstat.c +++ b/mpstat.c @@ -87,7 +87,8 @@ void usage(char *progname) progname); fprintf(stderr, _("Options are:\n" - "[ -A ] [ -I { SUM | CPU | SCPU | ALL } ] [ -u ] [ -P { [,...] | ALL } ] [ -V ]\n")); + "[ -A ] [ -I { SUM | CPU | SCPU | ALL } ] [ -u ]\n" + "[ -P { [,...] | ON | ALL } ] [ -V ]\n")); exit(1); } @@ -211,6 +212,7 @@ void write_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis, unsigned long long itv, int prev, int curr, char *prev_string, char *curr_string) { + struct stats_cpu *scc, *scp; int j = 0, offset, cpu; struct stats_irqcpu *p, *q, *p0, *q0; @@ -248,14 +250,27 @@ void write_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis, for (cpu = 1; cpu <= cpu_nr; cpu++) { + scc = st_cpu[curr] + cpu; + scp = st_cpu[prev] + cpu; + /* - * Check if we want stats about this CPU. + * Check if we want stats about this CPU. * CPU must have been explicitly selected using option -P, * else we display every CPU. */ if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) && USE_P_OPTION(flags)) continue; + if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys + + scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal + + scc->cpu_hardirq + scc->cpu_softirq) == 0) { + + /* Offline CPU found */ + + if (DISPLAY_ONLINE_CPU(flags)) + continue; + } + printf("%-11s %3d", curr_string, cpu - 1); for (j = 0; j < ic_nr; j++) { @@ -299,7 +314,7 @@ void write_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis, /* *************************************************************************** - * Core function used to display statistics + * Core function used to display statistics. * * IN: * @prev Position in array where statistics used as reference are. @@ -393,8 +408,6 @@ void write_stats_core(int prev, int curr, int dis, if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07)))) continue; - printf("%-11s %4d", curr_string, cpu - 1); - /* * If the CPU is offline then it is omited from /proc/stat * and the sum of all values is zero. @@ -403,19 +416,19 @@ void write_stats_core(int prev, int curr, int dis, if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys + scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal + scc->cpu_hardirq + scc->cpu_softirq) == 0) { - /* - * Set current struct fields (which have been set to zero) - * to values from previous iteration. Hence their values won't - * jump from zero when the CPU comes back online. - */ - *scc = *scp; - printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f" - " %6.2f %6.2f %6.2f\n", - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + if (!DISPLAY_ONLINE_CPU(flags)) { + printf("%-11s %4d" + " %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f" + " %6.2f %6.2f %6.2f\n", + curr_string, cpu - 1, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + } continue; } + printf("%-11s %4d", curr_string, cpu - 1); + /* Recalculate itv for current proc */ pc_itv = get_per_cpu_interval(scc, scp); @@ -492,13 +505,28 @@ void write_stats_core(int prev, int curr, int dis, if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07)))) continue; + if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys + + scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal + + scc->cpu_hardirq + scc->cpu_softirq) == 0) { + + /* This is an offline CPU */ + + if (!DISPLAY_ONLINE_CPU(flags)) { + printf("%-11s %4d" + " %9.2f\n", + curr_string, cpu - 1, + 0.0); + } + continue; + } + printf("%-11s %4d", curr_string, cpu - 1); /* Recalculate itv for current proc */ pc_itv = get_per_cpu_interval(scc, scp); if (!pc_itv) { - /* Current CPU is offline */ + /* This is a tickless CPU */ printf(" %9.2f\n", 0.0); } else { @@ -517,11 +545,30 @@ void write_stats_core(int prev, int curr, int dis, write_irqcpu_stats(st_softirqcpu, softirqcpu_nr, dis, itv, prev, curr, prev_string, curr_string); } + + /* Fix CPU counter values for every offline CPU */ + for (cpu = 1; cpu <= cpu_nr; cpu++) { + + scc = st_cpu[curr] + cpu; + scp = st_cpu[prev] + cpu; + + if ((scc->cpu_user + scc->cpu_nice + scc->cpu_sys + + scc->cpu_iowait + scc->cpu_idle + scc->cpu_steal + + scc->cpu_hardirq + scc->cpu_softirq) == 0) { + /* + * Offline CPU found. + * Set current struct fields (which have been set to zero) + * to values from previous iteration. Hence their values won't + * jump from zero when the CPU comes back online. + */ + *scc = *scp; + } + } } /* *************************************************************************** - * Print statistics average + * Print statistics average. * * IN: * @curr Position in array where statistics for current sample are. @@ -539,7 +586,7 @@ void write_stats_avg(int curr, int dis) /* *************************************************************************** - * Print statistics + * Print statistics. * * IN: * @curr Position in array where statistics for current sample are. @@ -859,7 +906,7 @@ int main(int argc, char **argv) dis_hdr++; for (t = strtok(argv[opt], ","); t; t = strtok(NULL, ",")) { - if (!strcmp(t, K_ALL)) { + if (!strcmp(t, K_ALL) || !strcmp(t, K_ON)) { if (cpu_nr) { dis_hdr = 9; } @@ -868,6 +915,10 @@ int main(int argc, char **argv) * Also indicate to display stats for CPU 'all'. */ memset(cpu_bitmap, 0xff, ((cpu_nr + 1) >> 3) + 1); + if (!strcmp(t, K_ON)) { + /* Display stats only for online CPU */ + flags |= F_P_ON; + } } else { if (strspn(t, DIGITS) != strlen(t)) { diff --git a/mpstat.h b/mpstat.h index 9bcf86d..13c0bdd 100644 --- a/mpstat.h +++ b/mpstat.h @@ -38,12 +38,16 @@ /* Indicate that option -P has been used */ #define F_P_OPTION 0x01 +/* Indicate that stats should be displayed on for online CPU ("-P ON") */ +#define F_P_ON 0x02 -#define USE_P_OPTION(m) (((m) & F_P_OPTION) == F_P_OPTION) +#define USE_P_OPTION(m) (((m) & F_P_OPTION) == F_P_OPTION) +#define DISPLAY_ONLINE_CPU(m) (((m) & F_P_ON) == F_P_ON) #define K_SUM "SUM" #define K_CPU "CPU" #define K_SCPU "SCPU" +#define K_ON "ON" #define NR_IRQCPU_PREALLOC 3