X-Git-Url: http://git.annexia.org/?p=virt-top.git;a=blobdiff_plain;f=virt-top%2Fvirt_top.ml;h=b30476677d247b3cd9961566890acbfa357b215e;hp=503016553607ca3c994d8c46c87d2fff3df7641a;hb=3d870f4841bb81800baeccaa531667b23e15d9d1;hpb=dbef8dd3bf00417e75a12c851b053e49c9e1a79e diff --git a/virt-top/virt_top.ml b/virt-top/virt_top.ml index 5030165..b304766 100644 --- a/virt-top/virt_top.ml +++ b/virt-top/virt_top.ml @@ -126,6 +126,7 @@ let uri = ref None let debug_file = ref "" let csv_enabled = ref false let csv_cpu = ref true +let csv_mem = ref true let csv_block = ref true let csv_net = ref true let init_file = ref DefaultInitFile @@ -171,13 +172,15 @@ let start_up () = "-b", Arg.Set batch_mode, " " ^ s_"Batch mode"; "-c", Arg.String set_uri, - "uri " ^ s_"Connect to URI (default: Xen)"; + "uri " ^ s_"Connect to libvirt URI"; "--connect", Arg.String set_uri, - "uri " ^ s_"Connect to URI (default: Xen)"; + "uri " ^ s_"Connect to libvirt URI"; "--csv", Arg.String set_csv, "file " ^ s_"Log statistics to CSV file"; "--no-csv-cpu", Arg.Clear csv_cpu, " " ^ s_"Disable CPU stats in CSV"; + "--no-csv-mem", Arg.Clear csv_mem, + " " ^ s_"Disable memory stats in CSV"; "--no-csv-block", Arg.Clear csv_block, " " ^ s_"Disable block device stats in CSV"; "--no-csv-net", Arg.Clear csv_net, @@ -197,7 +200,8 @@ let start_up () = "-n", Arg.Set_int iterations, "iterations " ^ s_"Number of iterations to run"; "-o", Arg.String set_sort, - "sort " ^ sprintf (f_"Set sort order (%s)") "cpu|mem|time|id|name"; + "sort " ^ sprintf (f_"Set sort order (%s)") + "cpu|mem|time|id|name|netrx|nettx|blockrdrq|blockwrrq"; "-s", Arg.Set secure_mode, " " ^ s_"Secure (\"kiosk\") mode"; "--script", Arg.Set script_mode, @@ -233,6 +237,7 @@ OPTIONS" in | _, "debug", filename -> debug_file := filename | _, "csv", filename -> set_csv filename | _, "csv-cpu", b -> csv_cpu := bool_of_string b + | _, "csv-mem", b -> csv_mem := bool_of_string b | _, "csv-block", b -> csv_block := bool_of_string b | _, "csv-net", b -> csv_net := bool_of_string b | _, "batch", b -> batch_mode := bool_of_string b @@ -268,7 +273,7 @@ OPTIONS" in prerr_endline (Libvirt.Virterror.to_string err); (* If non-root and no explicit connection URI, print a warning. *) if Unix.geteuid () <> 0 && name = None then ( - print_endline (s_"NB: If you want to monitor a local Xen hypervisor, you usually need to be root"); + print_endline (s_"NB: If you want to monitor a local hypervisor, you usually need to be root"); ); exit 1 in @@ -402,6 +407,8 @@ and rd_active = { (* The following are since the last slice, or 0 if cannot be calculated: *) rd_cpu_time : float; (* CPU time used in nanoseconds. *) rd_percent_cpu : float; (* CPU time as percent of total. *) + rd_mem_bytes : int64; (* Memory usage in bytes *) + rd_mem_percent: int64; (* Memory usage as percent of total *) (* The following are since the last slice, or None if cannot be calc'd: *) rd_block_rd_reqs : int64 option; (* Number of block device read rqs. *) rd_block_wr_reqs : int64 option; (* Number of block device write rqs. *) @@ -440,14 +447,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_usages 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, _, _) = @@ -510,6 +517,7 @@ let collect, clear_pcpu_display_data = rd_prev_block_stats = prev_block_stats; rd_prev_interface_stats = prev_interface_stats; rd_cpu_time = 0.; rd_percent_cpu = 0.; + rd_mem_bytes = 0L; rd_mem_percent = 0L; rd_block_rd_reqs = None; rd_block_wr_reqs = None; rd_block_rd_bytes = None; rd_block_wr_bytes = None; rd_block_rd_info = None; rd_block_wr_info = None; @@ -544,9 +552,14 @@ let collect, clear_pcpu_display_data = let cpu_time = Int64.to_float (rd.rd_info.D.cpu_time -^ prev_info.D.cpu_time) in let percent_cpu = 100. *. cpu_time /. total_cpu in + let mem_usage = rd.rd_info.D.memory in + let mem_percent = + 100L *^ rd.rd_info.D.memory /^ node_info.C.memory in let rd = { rd with rd_cpu_time = cpu_time; - rd_percent_cpu = percent_cpu } in + rd_percent_cpu = percent_cpu; + rd_mem_bytes = mem_usage; + rd_mem_percent = mem_percent} in name, Active rd (* For all other domains we can't calculate it, so leave as 0 *) | rd -> rd @@ -640,22 +653,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 @@ -668,37 +687,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; @@ -707,7 +704,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 @@ -892,9 +889,7 @@ let redraw = let rx_bytes = Show.int64_option rd.rd_net_rx_bytes in let tx_bytes = Show.int64_option rd.rd_net_tx_bytes in let percent_cpu = Show.percent rd.rd_percent_cpu in - let percent_mem = - 100L *^ rd.rd_info.D.memory /^ node_info.C.memory in - let percent_mem = Int64.to_float percent_mem in + let percent_mem = Int64.to_float rd.rd_mem_percent in let percent_mem = Show.percent percent_mem in let time = Show.time rd.rd_info.D.cpu_time in @@ -928,7 +923,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 @@ -947,8 +942,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 = @@ -956,9 +951,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); () @@ -1232,6 +1225,7 @@ let write_csv_header () = (* These fields are repeated for each domain: *) [ "Domain ID"; "Domain name"; ] @ (if !csv_cpu then [ "CPU (ns)"; "%CPU"; ] else []) @ + (if !csv_mem then [ "Mem (bytes)"; "%Mem";] else []) @ (if !csv_block && not !block_in_bytes then [ "Block RDRQ"; "Block WRRQ"; ] else []) @ (if !csv_block && !block_in_bytes @@ -1289,6 +1283,9 @@ let append_csv (if !csv_cpu then [ string_of_float rd.rd_cpu_time; string_of_float rd.rd_percent_cpu ] else []) @ + (if !csv_mem then [ + Int64.to_string rd.rd_mem_bytes; Int64.to_string rd.rd_mem_percent + ] else []) @ (if !csv_block then [ string_of_int64_option rd.rd_block_rd_info; string_of_int64_option rd.rd_block_wr_info; @@ -1344,9 +1341,7 @@ let dump_stdout let tx_bytes = if rd.rd_net_tx_bytes = None then " 0" else Show.int64_option rd.rd_net_tx_bytes in let percent_cpu = Show.percent rd.rd_percent_cpu in - let percent_mem = - 100L *^ rd.rd_info.D.memory /^ node_info.C.memory in - let percent_mem = Int64.to_float percent_mem in + let percent_mem = Int64.to_float rd.rd_mem_percent in let percent_mem = Show.percent percent_mem in let time = Show.time rd.rd_info.D.cpu_time in printf "%5d %c %s %s %s %s %s %s %s %s\n"