show `vcpu usages' by `virt-top -1'
authorHu Tao <hutao@cn.fujitsu.com>
Fri, 12 Oct 2012 12:45:26 +0000 (13:45 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 12 Oct 2012 12:45:26 +0000 (13:45 +0100)
Before this patch, `virt-top -1' shows total cpu usages
which euqal to `vcpu usages' + `hypervisor usages'. This
patch adds another column for domains showing `vcpu
usages'. An example is:

PHYCPU %CPU example_domain
   0   10.4 10.4  0.8
   1    1.6  1.6  1.4
   2    2.6  2.6  2.6
   3    0.0  0.0  0.1

RWMJ: I cleaned up this patch a little, but it should be
functionally the same.

virt-top/virt-top.pod
virt-top/virt_top.ml

index 56b61a1..4d81608 100755 (executable)
@@ -22,6 +22,12 @@ different virtualization systems.
 =item B<-1>
 
 Display physical CPUs by default (instead of domains).
 =item B<-1>
 
 Display physical CPUs by default (instead of domains).
+
+Under each domain column, two numbers are shown.  The first is
+the percentage of the physical CPU used by the domain and the
+hypervisor together.  The second is the percentage used by just
+the domain.
+
 When virt-top is running, use the I<1> key to toggle
 between physical CPUs and domains display.
 
 When virt-top is running, use the I<1> key to toggle
 between physical CPUs and domains display.
 
index eafad95..0aae24e 100644 (file)
@@ -672,10 +672,28 @@ let collect, clear_pcpu_display_data =
                 let domid = rd.rd_domid in
                 let maplen = C.cpumaplen nr_pcpus in
                 let cpu_stats = D.get_cpu_stats rd.rd_dom in
                 let domid = rd.rd_domid in
                 let maplen = C.cpumaplen nr_pcpus in
                 let cpu_stats = D.get_cpu_stats rd.rd_dom in
-                let rec find_cpu_usages = function
-                  | ("cpu_time", D.TypedFieldUInt64 usages) :: _ -> usages
-                  | _ :: params -> find_cpu_usages params
-                  | [] -> 0L in
+
+                 (* Note the terminology is confusing.
+                  *
+                  * In libvirt, cpu_time is the total time (hypervisor + vCPU).
+                  * vcpu_time is the time only taken by the vCPU,
+                  * excluding time taken inside the hypervisor.
+                  *
+                  * For each pCPU, libvirt may return either "cpu_time"
+                  * or "vcpu_time" or neither or both.  This function
+                  * returns an array pair [|cpu_time, vcpu_time|];
+                  * if either is missing it is returned as 0.
+                  *)
+                let find_cpu_usages params =
+                   let rec find_uint64_field name = function
+                     | (n, D.TypedFieldUInt64 usage) :: _ when n = name -> usage
+                     | _ :: params -> find_uint64_field name params
+                     | [] -> 0L
+                   in
+                   [| find_uint64_field "cpu_time" params;
+                      find_uint64_field "vcpu_time" params |]
+                 in
+
                 let pcpu_usages = Array.map find_cpu_usages cpu_stats in
                 let maxinfo = rd.rd_info.D.nr_virt_cpu in
                 let nr_vcpus, vcpu_infos, cpumaps =
                 let pcpu_usages = Array.map find_cpu_usages cpu_stats in
                 let maxinfo = rd.rd_info.D.nr_virt_cpu in
                 let nr_vcpus, vcpu_infos, cpumaps =
@@ -704,25 +722,32 @@ let collect, clear_pcpu_display_data =
 
        (* Rearrange the data into a matrix.  Major axis (down) is
         * pCPUs.  Minor axis (right) is domains.  At each node we store:
 
        (* Rearrange the data into a matrix.  Major axis (down) is
         * pCPUs.  Minor axis (right) is domains.  At each node we store:
-        *  cpu_time (on this pCPU only, nanosecs),
+        *  cpu_time hypervisor + domain (on this pCPU only, nanosecs),
+        *  vcpu_time domain only (on this pCPU only, nanosecs).
         *)
         *)
-       let pcpus = Array.make_matrix nr_pcpus nr_doms 0L in
+        let make_3d_array dimx dimy dimz e =
+          Array.init dimx (fun _ -> Array.make_matrix dimy dimz e)
+        in
+       let pcpus = make_3d_array nr_pcpus nr_doms 2 0L in
 
        List.iteri (
          fun di (domid, name, nr_vcpus, vcpu_infos, pcpu_usages,
                  prev_pcpu_usages, cpumaps, maplen) ->
            (* Which pCPUs can this dom run on? *)
            for p = 0 to Array.length pcpu_usages - 1 do
 
        List.iteri (
          fun di (domid, name, nr_vcpus, vcpu_infos, pcpu_usages,
                  prev_pcpu_usages, cpumaps, maplen) ->
            (* Which pCPUs can this dom run on? *)
            for p = 0 to Array.length pcpu_usages - 1 do
-             pcpus.(p).(di) <- pcpu_usages.(p) -^ prev_pcpu_usages.(p)
-           done
+             pcpus.(p).(di).(0) <-
+                pcpu_usages.(p).(0) -^ prev_pcpu_usages.(p).(0);
+             pcpus.(p).(di).(1) <-
+                pcpu_usages.(p).(1) -^ prev_pcpu_usages.(p).(1)
+            done
        ) doms;
 
        ) doms;
 
-       (* Sum the CPU time used by each pCPU, for the %CPU column. *)
+       (* Sum the total CPU time used by each pCPU, for the %CPU column. *)
        let pcpus_cpu_time = Array.map (
          fun row ->
            let cpu_time = ref 0L in
            for di = 0 to Array.length row-1 do
        let pcpus_cpu_time = Array.map (
          fun row ->
            let cpu_time = ref 0L in
            for di = 0 to Array.length row-1 do
-             let t = row.(di) in
+             let t = row.(di).(0) in
              cpu_time := !cpu_time +^ t
            done;
            Int64.to_float !cpu_time
              cpu_time := !cpu_time +^ t
            done;
            Int64.to_float !cpu_time
@@ -943,7 +968,7 @@ let redraw =
             List.map (
               fun (_, name, _, _, _, _, _, _) ->
                 let len = String.length name in
             List.map (
               fun (_, name, _, _, _, _, _, _) ->
                 let len = String.length name in
-                let width = max (len+1) 7 in
+                let width = max (len+1) 12 in
                 pad width name
             ) doms
           ) in
                 pad width name
             ) doms
           ) in
@@ -961,17 +986,27 @@ let redraw =
 
             List.iteri (
               fun di (domid, name, _, _, _, _, _, _) ->
 
             List.iteri (
               fun di (domid, name, _, _, _, _, _, _) ->
-                let t = pcpus.(p).(di) in
+                let t = pcpus.(p).(di).(0) in (* hypervisor + domain *)
+                let t_only = pcpus.(p).(di).(1) in (* domain only *)
                 let len = String.length name in
                 let len = String.length name in
-                let width = max (len+1) 7 in
-                let str =
+                let width = max (len+1) 12 in
+                let str_t =
                   if t <= 0L then ""
                   else (
                     let t = Int64.to_float t in
                     let percent = 100. *. t /. total_cpu_per_pcpu in
                   if t <= 0L then ""
                   else (
                     let t = Int64.to_float t in
                     let percent = 100. *. t /. total_cpu_per_pcpu in
-                    sprintf "%s " (Show.percent percent)
+                    Show.percent percent
                   ) in
                   ) in
-                addstr (pad width str);
+                 let str_t_only =
+                    if t_only <= 0L then ""
+                    else (
+                      let t_only = Int64.to_float t_only in
+                      let percent = 100. *. t_only /. total_cpu_per_pcpu in
+                      Show.percent percent
+                    ) in
+                 addstr (pad 5 str_t);
+                 addstr (pad 5 str_t_only);
+                 addstr (pad (width-10) " ");
                 ()
             ) doms
         ) pcpus;
                 ()
             ) doms
         ) pcpus;