]> granicus.if.org Git - sysstat/commitdiff
Option "-P ON" added to mpstat.
authorSebastien Godard <sysstat@orange.fr>
Mon, 15 Aug 2011 14:00:05 +0000 (16:00 +0200)
committerSebastien Godard <sysstat@orange.fr>
Mon, 15 Aug 2011 14:02:40 +0000 (16:02 +0200)
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.

CHANGES
man/mpstat.1
mpstat.c
mpstat.h

diff --git a/CHANGES b/CHANGES
index 9532368134afa81dbc9279582cecf192577a5cb7..7551cc515ad71ca8d8106171e80ceeed97cfcc6e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,10 +5,12 @@ xxxx/xx/xx: Version 10.0.2 - Sebastien Godard (sysstat <at> 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).
index 1d0527d8da83a86fa4ebdc7844c23742488a95f2..1f1fdb3bf185219cabefe3d044a2985b5d6910f9 100644 (file)
@@ -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
index 118036a75967dc19527e385c8f0538075714dff8..a8669dcca3c5a94e4e4c21e93fbb6c7a1bcfe4cb 100644 (file)
--- 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 { <cpu> [,...] | ALL } ] [ -V ]\n"));
+                         "[ -A ] [ -I { SUM | CPU | SCPU | ALL } ] [ -u ]\n"
+                         "[ -P { <cpu> [,...] | 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)) {
index 9bcf86dc2a741a83929182d2fdd773db8fcdbca7..13c0bdddb8e804d6b5bf8aeec0e14571f0c630f4 100644 (file)
--- a/mpstat.h
+++ b/mpstat.h
 
 /* 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