]> granicus.if.org Git - procps-ng/commitdiff
vmstat: add guest time to stat
authorChristian Borntraeger <borntraeger@de.ibm.com>
Wed, 28 Apr 2021 08:51:34 +0000 (18:51 +1000)
committerCraig Small <csmall@dropbear.xyz>
Wed, 28 Apr 2021 08:51:34 +0000 (18:51 +1000)
Since 2.6.24/33 the kernel knows about guest and guest nice time. That
is the time that is spend in KVM guests. To handle userspace programs
that do not know about this the guest time is also added to user.

Let us provide a guest time column in vmstat that collects both guest
and guest nice into a gu value.

We also subtract that value from the user time as we are now aware of
the guest value.

This commit is different to !113 in several ways:
 * newlib already knows about these to values
 * vmstat summary already shows these values
 * non-wide vmstat squishes the values

So its around the wide vmstat output.

References:
 procps-ng/procps!113
Signed-off-by: Craig Small <csmall@dropbear.xyz>
vmstat.8
vmstat.c

index ebe15b025c7549621fcb1d8e65c52fa5fc62b169..b2c6f29d9c500cc2c7951c9bd3eee4364cfdd193 100644 (file)
--- a/vmstat.8
+++ b/vmstat.8
@@ -139,6 +139,7 @@ sy: Time spent running kernel code.  (system time)
 id: Time spent idle.  Prior to Linux 2.5.41, this includes IO\-wait time.
 wa: Time spent waiting for IO.  Prior to Linux 2.5.41, included in idle.
 st: Time stolen from a virtual machine.  Prior to Linux 2.6.11, unknown.
+gu: Time spent running KVM guest code (guest time, including guest nice).
 .fi
 .PP
 .SH "FIELD DESCRIPTION FOR DISK MODE"
index 960d03b21d80ececf3e88ed0c0ea215c27d1af14..86dacd3805f8384718fe256d05b03631b14a0b5b 100644 (file)
--- a/vmstat.c
+++ b/vmstat.c
@@ -102,7 +102,9 @@ static enum stat_item First_stat_items[] = {
     STAT_TIC_SOFTIRQ,
     STAT_TIC_IDLE,
     STAT_TIC_IOWAIT,
-    STAT_TIC_STOLEN
+    STAT_TIC_STOLEN,
+    STAT_TIC_GUEST,
+    STAT_TIC_GUEST_NICE
 };
 static enum stat_item Loop_stat_items[] = {
     STAT_SYS_PROC_RUNNING,
@@ -116,12 +118,15 @@ static enum stat_item Loop_stat_items[] = {
     STAT_TIC_DELTA_SOFTIRQ,
     STAT_TIC_DELTA_IDLE,
     STAT_TIC_DELTA_IOWAIT,
-    STAT_TIC_DELTA_STOLEN
+    STAT_TIC_DELTA_STOLEN,
+    STAT_TIC_DELTA_GUEST,
+    STAT_TIC_DELTA_GUEST_NICE
 };
 enum Rel_statitems {
     stat_PRU, stat_PBL, stat_INT, stat_CTX,
     stat_USR, stat_NIC, stat_SYS, stat_IRQ, stat_SRQ,
-    stat_IDL, stat_IOW, stat_STO, MAX_stat
+    stat_IDL, stat_IOW, stat_STO, stat_GST, stat_GNI,
+    MAX_stat
 };
 
 static enum meminfo_item Mem_items[] = {
@@ -247,13 +252,13 @@ static void new_header(void)
     const char *header =
         _("procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----");
     const char *wide_header =
-        _("--procs-- -----------------------memory---------------------- ---swap-- -----io---- -system-- --------cpu--------");
+        _("--procs-- -----------------------memory---------------------- ---swap-- -----io---- -system-- ----------cpu----------");
     const char *timestamp_header = _(" -----timestamp-----");
 
     const char format[] =
         "%2s %2s %6s %6s %6s %6s %4s %4s %5s %5s %4s %4s %2s %2s %2s %2s %2s";
     const char wide_format[] =
-        "%2s %2s %12s %12s %12s %12s %4s %4s %5s %5s %4s %4s %3s %3s %3s %3s %3s";
+        "%4s %4s %12s %12s %12s %12s %4s %4s %5s %5s %4s %4s %3s %3s %3s %3s %3s %3s";
 
 
     printf("%s", w_option ? wide_header : header);
@@ -303,7 +308,9 @@ static void new_header(void)
         /* Translation Hint: max 2 chars */
          _("wa"),
         /* Translation Hint: max 2 chars */
-         _("st"));
+         _("st"),
+        /* Translation Hint: max 2 chars */
+         _("gu"));
 
     if (t_option) {
         (void) time( &the_time );
@@ -340,12 +347,12 @@ static void new_format(void)
     const char format[] =
         "%2lu %2lu %6lu %6lu %6lu %6lu %4u %4u %5u %5u %4u %4u %2u %2u %2u %2u %2u";
     const char wide_format[] =
-        "%4lu %4lu %12lu %12lu %12lu %12lu %4u %4u %5u %5u %4u %4u %3u %3u %3u %3u %3u";
+        "%4lu %4lu %12lu %12lu %12lu %12lu %4u %4u %5u %5u %4u %4u %3u %3u %3u %3u %3u %3u";
 
     unsigned int tog = 0;    /* toggle switch for cleaner code */
     unsigned int i;
     long hz;
-    long long cpu_use, cpu_sys, cpu_idl, cpu_iow, cpu_sto;
+    long long cpu_use, cpu_sys, cpu_idl, cpu_iow, cpu_sto, cpu_gue;
     long long Div, divo2;
     unsigned long pgpgin[2], pgpgout[2], pswpin[2] = {0,0}, pswpout[2];
     unsigned int sleep_half;
@@ -388,6 +395,7 @@ static void new_format(void)
     cpu_idl = TICv(stat_IDL);
     cpu_iow = TICv(stat_IOW);
     cpu_sto = TICv(stat_STO);
+    cpu_gue = TICv(stat_GST) + TICv(stat_GNI);
 
     pgpgin[tog] = VMSTAT_GET(vm_info, VMSTAT_PGPGIN, ul_int);
     pgpgout[tog] = VMSTAT_GET(vm_info, VMSTAT_PGPGOUT, ul_int);
@@ -403,6 +411,7 @@ static void new_format(void)
         cpu_idl = 1;
     }
     divo2 = Div / 2UL;
+    cpu_use = (cpu_use >= cpu_gue)? cpu_use - cpu_gue : 0;
 
     printf(w_option ? wide_format : format,
            SYSv(stat_PRU),
@@ -421,7 +430,8 @@ static void new_format(void)
            (unsigned)( (100*cpu_sys        + divo2) / Div ),
            (unsigned)( (100*cpu_idl        + divo2) / Div ),
            (unsigned)( (100*cpu_iow        + divo2) / Div ),
-           (unsigned)( (100*cpu_sto        + divo2) / Div )
+           (unsigned)( (100*cpu_sto        + divo2) / Div ),
+           (unsigned)( (100*cpu_gue        + divo2) / Div )
     );
 
     if (t_option) {
@@ -445,6 +455,7 @@ static void new_format(void)
         cpu_idl = DTICv(stat_IDL);
         cpu_iow = DTICv(stat_IOW);
         cpu_sto = DTICv(stat_STO);
+        cpu_gue = TICv(stat_GST) + TICv(stat_GNI);
         pgpgin[tog] = VMSTAT_GET(vm_info, VMSTAT_PGPGIN, ul_int);
         pgpgout[tog] = VMSTAT_GET(vm_info, VMSTAT_PGPGOUT, ul_int);
         pswpin[tog] = VMSTAT_GET(vm_info, VMSTAT_PSWPIN, ul_int);
@@ -473,6 +484,15 @@ static void new_format(void)
         Div = cpu_use + cpu_sys + cpu_idl + cpu_iow + cpu_sto;
         if (!Div) Div = 1, cpu_idl = 1;
         divo2 = Div / 2UL;
+
+        /* guest time is also in user time, we need to subtract. Due to timing
+         * effects guest could be larger than user. We use 0 that case */
+        if (cpu_use >= cpu_gue) {
+            cpu_use -= cpu_gue;
+        } else {
+            cpu_use = 0;
+        }
+
         printf(w_option ? wide_format : format,
                SYSv(stat_PRU),
                SYSv(stat_PBL),
@@ -501,7 +521,9 @@ static void new_format(void)
                /* wa */
                (unsigned)( (100*cpu_iow+divo2)/Div ),
                /* st */
-               (unsigned)( (100*cpu_sto+divo2)/Div )
+               (unsigned)( (100*cpu_sto+divo2)/Div ),
+              /* gu */
+               (unsigned)( (100*cpu_gue+divo2)/Div )
         );
 
         if (t_option) {