Old "virt-top -1" is not correct, its output is generated by guess:
use average usage for pinned physical CPUs.
example(old "virt-top -1"):
PHYCPU %CPU rhel6 Windows
0 0.6 0.1= 0.5=
1 0.6 0.1= 0.5=#
2 0.6 0.1= 0.5=
3 0.6 0.1=# 0.5=
The output almost makes no sense(all the value are just average, not real).
This is new implement, it use cpuacct cgroup to gain *real* physical usages
via cpuacct cgroup by virDomainGetPcpusUsage() API.
new result:
PHYCPU %CPU rhel6 Windows
0 3.3 2.9 0.3
1 1.7 1.1 0.6
2 3.5 1.8 1.6
3 3.4 1.6 1.8
PHYCPU %CPU rhel6 Windows
0 1.2 0.8 0.4
1 1.6 1.6
2 2.2 1.7 0.5
3 3.0 2.5 0.5
Note: average flag(=) is dropped, there is not average value in here.
Note: running flag(#) is dropped, because if the value is not empty,
it means the guest was once running in the physical CPU in this period
between updates.
Acked-by: "Richard W.M. Jones" <rjones(a)redhat.com>
Signed-off-by: Lai Jiangshan <laijs(a)cn.fujitsu.com>
---
virt-top/virt_top.ml | 75 +++++++++++++++++--------------------------------
1 files changed, 26 insertions(+), 49 deletions(-)
diff --git a/virt-top/virt_top.ml b/virt-top/virt_top.ml
index ef5ac67..2556b77 100644
--- a/virt-top/virt_top.ml
+++ b/virt-top/virt_top.ml
@@ -446,14 +446,14 @@ let collect, clear_pcpu_display_data =
let last_info = Hashtbl.create 13 in
let last_time = ref (Unix.gettimeofday ()) in
- (* Save vcpuinfo structures across redraws too (only for pCPU display). *)
- let last_vcpu_info = Hashtbl.create 13 in
+ (* Save pcpu_usages structures across redraws too (only for pCPU display). *)
+ let last_pcpu_usages = Hashtbl.create 13 in
let clear_pcpu_display_data () =
- (* Clear out vcpu_info used by PCPUDisplay display_mode
+ (* Clear out pcpu_info used by PCPUDisplay display_mode
* when we switch back to TaskDisplay mode.
*)
- Hashtbl.clear last_vcpu_info
+ Hashtbl.clear last_pcpu_usages
in
let collect (conn, _, _, _, _, node_info, _, _) =
@@ -652,22 +652,23 @@ let collect, clear_pcpu_display_data =
(try
let domid = rd.rd_domid in
let maplen = C.cpumaplen nr_pcpus in
+ let pcpu_usages = D.get_pcpu_usages rd.rd_dom nr_pcpus in
let maxinfo = rd.rd_info.D.nr_virt_cpu in
let nr_vcpus, vcpu_infos, cpumaps =
D.get_vcpus rd.rd_dom maxinfo maplen in
- (* Got previous vcpu_infos for this domain? *)
- let prev_vcpu_infos =
- try Some (Hashtbl.find last_vcpu_info domid)
+ (* Got previous pcpu_usages for this domain? *)
+ let prev_pcpu_usages =
+ try Some (Hashtbl.find last_pcpu_usages domid)
with Not_found -> None in
- (* Update last_vcpu_info. *)
- Hashtbl.replace last_vcpu_info domid vcpu_infos;
-
- (match prev_vcpu_infos with
- | Some prev_vcpu_infos
- when Array.length prev_vcpu_infos = Array.length vcpu_infos ->
- Some (domid, name, nr_vcpus, vcpu_infos, prev_vcpu_infos,
- cpumaps, maplen)
+ (* Update last_pcpu_usages. *)
+ Hashtbl.replace last_pcpu_usages domid pcpu_usages;
+
+ (match prev_pcpu_usages with
+ | Some prev_pcpu_usages
+ when Array.length prev_pcpu_usages = Array.length pcpu_usages ->
+ Some (domid, name, nr_vcpus, vcpu_infos, pcpu_usages,
+ prev_pcpu_usages, cpumaps, maplen)
| _ -> None (* ignore missing / unequal length prev_vcpu_infos *)
);
with
@@ -680,37 +681,15 @@ 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:
* cpu_time (on this pCPU only, nanosecs),
- * average? (if set, then cpu_time is an average because the
- * vCPU is pinned to more than one pCPU)
- * running? (if set, we were instantaneously running on this pCPU)
*)
- let empty_node = (0L, false, false) in
- let pcpus = Array.make_matrix nr_pcpus nr_doms empty_node in
+ let pcpus = Array.make_matrix nr_pcpus nr_doms 0L in
List.iteri (
- fun di (domid, name, nr_vcpus, vcpu_infos, prev_vcpu_infos,
- cpumaps, maplen) ->
+ fun di (domid, name, nr_vcpus, vcpu_infos, pcpu_usages,
+ prev_pcpu_usages, cpumaps, maplen) ->
(* Which pCPUs can this dom run on? *)
- for v = 0 to nr_vcpus-1 do
- let pcpu = vcpu_infos.(v).D.cpu in (* instantaneous pCPU *)
- let nr_poss_pcpus = ref 0 in (* how many pcpus can it run on? *)
- for p = 0 to nr_pcpus-1 do
- (* vcpu v can reside on pcpu p *)
- if C.cpu_usable cpumaps maplen v p then
- incr nr_poss_pcpus
- done;
- let nr_poss_pcpus = Int64.of_int !nr_poss_pcpus in
- for p = 0 to nr_pcpus-1 do
- (* vcpu v can reside on pcpu p *)
- if C.cpu_usable cpumaps maplen v p then
- let vcpu_time_on_pcpu =
- vcpu_infos.(v).D.vcpu_time
- -^ prev_vcpu_infos.(v).D.vcpu_time in
- let vcpu_time_on_pcpu =
- vcpu_time_on_pcpu /^ nr_poss_pcpus in
- pcpus.(p).(di) <-
- (vcpu_time_on_pcpu, nr_poss_pcpus > 1L, p = pcpu)
- done
+ for p = 0 to Array.length pcpu_usages - 1 do
+ pcpus.(p).(di) <- (pcpu_usages.(p) -^ prev_pcpu_usages.(p))
done
) doms;
@@ -719,7 +698,7 @@ let collect, clear_pcpu_display_data =
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) in
cpu_time := !cpu_time +^ t
done;
Int64.to_float !cpu_time
@@ -938,7 +917,7 @@ let redraw =
let dom_names =
String.concat "" (
List.map (
- fun (_, name, _, _, _, _, _) ->
+ fun (_, name, _, _, _, _, _, _) ->
let len = String.length name in
let width = max (len+1) 7 in
pad width name
@@ -957,8 +936,8 @@ let redraw =
addch ' ';
List.iteri (
- fun di (domid, name, _, _, _, _, _) ->
- let t, is_average, is_running = pcpus.(p).(di) in
+ fun di (domid, name, _, _, _, _, _, _) ->
+ let t = pcpus.(p).(di) in
let len = String.length name in
let width = max (len+1) 7 in
let str =
@@ -966,9 +945,7 @@ let redraw =
else (
let t = Int64.to_float t in
let percent = 100. *. t /. total_cpu_per_pcpu in
- sprintf "%s%c%c " (Show.percent percent)
- (if is_average then '=' else ' ')
- (if is_running then '#' else ' ')
+ sprintf "%s " (Show.percent percent)
) in
addstr (pad width str);
()
--
1.7.4.4