[libvirt] [PATCH 1/1 V4] virt-top: correct "virt-top -1" command via cpuacct cgroup
Lai Jiangshan
laijs at cn.fujitsu.com
Thu Feb 16 07:27:02 UTC 2012
Hi, Richard
virt-top and ocaml site patches can work and are completed weeks ago since
public API of libvirt is merged. Could you merged them?
virt-top and ocaml site patches only depend on the public API of libvirt.
but the testing of them may depend on the qemu-driver-site patch of libvirt,
which is sent today.
Thanks,
Lai
On 02/08/2012 04:59 PM, Lai Jiangshan wrote:
>
>
> 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 virDomainGetCPUStats() API.
>
> new result:
>
> PHYCPU %CPU rhel6 Windows
> 0 1.3 0.3 1.0
> 1 2.3 0.3 2.0
> 2 2.2 0.5 1.7
> 3 2.5 0.4 2.1
>
>
> PHYCPU %CPU rhel6 Windows
> 0 1.7 0.4 1.3
> 1 3.6 1.0 2.7
> 2 1.6 0.4 1.2
> 3 4.8 3.1 1.7
>
>
>
> 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.
>
> Changed from V3:
> use new virDomainGetCPUStats() libvirt-API.
> add a new function find_usages_from_stats() to gain cpu usages.
>
> Acked-by: "Richard W.M. Jones" <rjones at redhat.com>
> Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
> ---
> virt-top/virt_top.ml | 80 +++++++++++++++++++------------------------------
> 1 files changed, 31 insertions(+), 49 deletions(-)
>
> diff --git a/virt-top/virt_top.ml b/virt-top/virt_top.ml
> index ef5ac67..f7bd072 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,28 @@ let collect, clear_pcpu_display_data =
> (try
> let domid = rd.rd_domid in
> let maplen = C.cpumaplen nr_pcpus in
> + let cpu_stats = D.get_cpu_stats rd.rd_dom nr_pcpus in
> + let rec find_usages_from_stats = (function
> + | ("cpu_time", D.TypedFieldUInt64(usages)) :: _ -> usages
> + | (_, _) :: params -> find_usages_from_stats params
> + | [] -> 0L) in
> + let pcpu_usages = Array.map find_usages_from_stats cpu_stats 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 +686,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 +703,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 +922,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 +941,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 +950,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);
> ()
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
>
More information about the libvir-list
mailing list