[virt-tools-list] [PATCH] virt-top: add a switch to show block I/O statistics in bytes
KAMEZAWA Hiroyuki
kamezawa.hiroyu at jp.fujitsu.com
Thu Jan 27 04:30:57 UTC 2011
I'm sorry this patch is onto my --stream mode patch. I'll change the order
if necessary.
==
vir-top shows RDRQ/WRRQ for domains in default mode(TASK_DISPLAY)
and csv mode and stream mode(I added).
In BlockDevice mode, RDBY/WRBY/RDRQ/WRRQ are all shown.
This patch allows to show RDBY/WRBY in TASK_DISPLAY and csv, stream mode
by start option --block-in-bytes or key *B* in curses display.
IIUC, we cannot estimate I/O througput of MB/sec from the number of
request/sec. This patch allows to show amount of I/O in bytes.
If display update timing is 1 sec, this shows I/O throuput as xMB/sec.
I added a NOTE for manual about what the value RDBY/WRBY/RDRQ/WREQ shows.
Following is an output when I ran 'dd' in 13MB/sec on the guest RHEL6.
and updates are done in 1sec.
virt-top time 13:14:44 Host bluextal x86_64 8/8CPU 3165MHz 24033MB
ID S RDBY WRBY RXBY TXBY %CPU %MEM TIME NAME
7 R 0 0 0 0 0.4 17.0 16:10.97 Guest01
8 R 0 13M 0 0 1.2 34.0 33:14.95 RHEL6
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu at jp.fujitsu.com>
---
virt-top/virt-top.pod | 18 +++++++++++++
virt-top/virt_top.ml | 69 ++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 74 insertions(+), 13 deletions(-)
Index: virt-top-1.0.5/virt-top/virt_top.ml
===================================================================
--- virt-top-1.0.5.orig/virt-top/virt_top.ml
+++ virt-top-1.0.5/virt-top/virt_top.ml
@@ -131,6 +131,7 @@ let csv_net = ref true
let init_file = ref DefaultInitFile
let script_mode = ref false
let stream_mode = ref false
+let block_in_bytes = ref false
(* Tuple of never-changing data returned by start_up function. *)
type setup =
@@ -203,6 +204,8 @@ let start_up () =
" " ^ s_"Run from a script (no user interface)";
"--stream", Arg.Set stream_mode,
" " ^ s_"dump output to stdout (no userinterface)";
+ "--block-in-bytes", Arg.Set block_in_bytes,
+ " " ^ s_"show block device load in bytes rather than reqs";
"--version", Arg.Unit display_version,
" " ^ s_"Display version number and exit";
] in
@@ -236,6 +239,7 @@ OPTIONS" in
| _, "secure", b -> secure_mode := bool_of_string b
| _, "script", b -> script_mode := bool_of_string b
| _, "stream", b -> stream_mode := bool_of_string b
+ | _, "block-in-bytes", b -> block_in_bytes := bool_of_string b
| _, "end-time", t -> set_end_time t
| _, "overwrite-init-file", "false" -> no_init_file ()
| lineno, key, _ ->
@@ -401,6 +405,12 @@ and rd_active = {
(* 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. *)
+ rd_block_rd_bytes : int64 option; (* Number of bytes block device read *)
+ rd_block_wr_bytes : int64 option; (* Number of bytes block device write *)
+ (* _info fields includes the number considering --block_in_bytes option *)
+ rd_block_rd_info : int64 option; (* Block device read info for user *)
+ rd_block_wr_info : int64 option; (* Block device read info for user *)
+
rd_net_rx_bytes : int64 option; (* Number of bytes received. *)
rd_net_tx_bytes : int64 option; (* Number of bytes transmitted. *)
}
@@ -501,6 +511,8 @@ let collect, clear_pcpu_display_data =
rd_prev_interface_stats = prev_interface_stats;
rd_cpu_time = 0.; rd_percent_cpu = 0.;
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;
rd_net_rx_bytes = None; rd_net_tx_bytes = None;
})
with
@@ -562,10 +574,23 @@ let collect, clear_pcpu_display_data =
block_stats.D.rd_req -^ prev_block_stats.D.rd_req in
let write_reqs =
block_stats.D.wr_req -^ prev_block_stats.D.wr_req in
+ let read_bytes =
+ block_stats.D.rd_bytes -^ prev_block_stats.D.rd_bytes in
+ let write_bytes =
+ block_stats.D.wr_bytes -^ prev_block_stats.D.wr_bytes in
let rd = { rd with
rd_block_rd_reqs = Some read_reqs;
- rd_block_wr_reqs = Some write_reqs } in
+ rd_block_wr_reqs = Some write_reqs;
+ rd_block_rd_bytes = Some read_bytes;
+ rd_block_wr_bytes = Some write_bytes;
+ } in
+ let rd = { rd with
+ rd_block_rd_info = if !block_in_bytes then
+ rd.rd_block_rd_bytes else rd.rd_block_rd_reqs;
+ rd_block_wr_info = if !block_in_bytes then
+ rd.rd_block_wr_bytes else rd.rd_block_wr_reqs;
+ } in
name, Active rd
(* For all other domains we can't calculate it, so leave as None. *)
| rd -> rd
@@ -849,8 +874,12 @@ let redraw =
(* Print domains. *)
attron A.reverse;
- mvaddstr header_lineno 0
- (pad cols " ID S RDRQ WRRQ RXBY TXBY %CPU %MEM TIME NAME");
+ let header_string = if !block_in_bytes
+ then " ID S RDBY WRBY RXBY TXBY %CPU %MEM TIME NAME"
+ else " ID S RDRQ WRRQ RXBY TXBY %CPU %MEM TIME NAME"
+ in
+ mvaddstr header_lineno 0
+ (pad cols header_string);
attroff A.reverse;
let rec loop lineno = function
@@ -858,8 +887,8 @@ let redraw =
| (name, Active rd) :: doms ->
if lineno < lines then (
let state = show_state rd.rd_info.D.state in
- let rd_req = Show.int64_option rd.rd_block_rd_reqs in
- let wr_req = Show.int64_option rd.rd_block_wr_reqs in
+ let rd_req = Show.int64_option rd.rd_block_rd_info in
+ let wr_req = Show.int64_option rd.rd_block_wr_info in
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
@@ -1203,7 +1232,10 @@ 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_block then [ "Block RDRQ"; "Block WRRQ"; ] else []) @
+ (if !csv_block && not !block_in_bytes
+ then [ "Block RDRQ"; "Block WRRQ"; ] else []) @
+ (if !csv_block && !block_in_bytes
+ then [ "Block RDBY"; "Block WRBY"; ] else []) @
(if !csv_net then [ "Net RXBY"; "Net TXBY" ] else [])
)
@@ -1258,8 +1290,8 @@ let append_csv
string_of_float rd.rd_cpu_time; string_of_float rd.rd_percent_cpu
] else []) @
(if !csv_block then [
- string_of_int64_option rd.rd_block_rd_reqs;
- string_of_int64_option rd.rd_block_wr_reqs;
+ string_of_int64_option rd.rd_block_rd_info;
+ string_of_int64_option rd.rd_block_wr_info;
] else []) @
(if !csv_net then [
string_of_int64_option rd.rd_net_rx_bytes;
@@ -1282,7 +1314,10 @@ let dump_stdout
printable_time hostname node_info.C.model node_info.C.cpus nr_pcpus
node_info.C.mhz (node_info.C.memory /^ 1024L);
(* dump domain information one by one *)
- printf " ID S RDRQ WRRQ RXBY TXBY %%CPU %%MEM TIME NAME\n";
+ let rd, wr = if !block_in_bytes then "RDBY", "WRBY" else "RDRQ", "WRRQ"
+ in
+ printf " ID S %s %s RXBY TXBY %%CPU %%MEM TIME NAME\n" rd wr;
+
(* sort by ID *)
let doms =
let compare =
@@ -1299,10 +1334,10 @@ let dump_stdout
let dump_domain = fun name rd
-> begin
let state = show_state rd.rd_info.D.state in
- let rd_req = if rd.rd_block_rd_reqs = None then " 0"
- else Show.int64_option rd.rd_block_rd_reqs in
- let wr_req = if rd.rd_block_wr_reqs = None then " 0"
- else Show.int64_option rd.rd_block_wr_reqs in
+ let rd_req = if rd.rd_block_rd_info = None then " 0"
+ else Show.int64_option rd.rd_block_rd_info in
+ let wr_req = if rd.rd_block_wr_info = None then " 0"
+ else Show.int64_option rd.rd_block_wr_info in
let rx_bytes = if rd.rd_net_rx_bytes = None then " 0"
else Show.int64_option rd.rd_net_rx_bytes in
let tx_bytes = if rd.rd_net_tx_bytes = None then " 0"
@@ -1388,6 +1423,7 @@ and get_key_press setup =
else if k = Char.code '2' then toggle_net_display ()
else if k = Char.code '3' then toggle_block_display ()
else if k = Char.code 'W' then write_init_file ()
+ else if k = Char.code 'B' then toggle_block_in_bytes_mode ()
else unknown_command k
)
@@ -1533,6 +1569,12 @@ and toggle_block_display () = (* key 3
| TaskDisplay | NetDisplay -> BlockDisplay
| BlockDisplay -> TaskDisplay
+and toggle_block_in_bytes_mode () = (* key B *)
+ block_in_bytes :=
+ match !block_in_bytes with
+ | false -> true
+ | true -> false
+
(* Write an init file. *)
and write_init_file () =
match !init_file with
@@ -1661,6 +1703,7 @@ and show_help (_, _, _, _, _, _, hostnam
key "q" (s_"Quit");
key "d s" (s_"Set update interval");
key "h" (s_"Help");
+ key "B" (s_"toggle block info req/bytes");
(* Sort order. *)
ignore (get_lineno ());
Index: virt-top-1.0.5/virt-top/virt-top.pod
===================================================================
--- virt-top-1.0.5.orig/virt-top/virt-top.pod
+++ virt-top-1.0.5/virt-top/virt-top.pod
@@ -158,6 +158,10 @@ when used together with the I<--csv> and
Stream mode. All output will be dumped out to stdout. This will be
useful when used in shell script etc. There will be no user interface.
+=item B<--block-in-bytes>
+
+Show I/O statistics in Bytes. Default is shown in the number of Requests.
+
=item B<--end-time time>
The program will exit at the I<time> given.
@@ -231,6 +235,10 @@ Displays help.
Change the delay between screen updates.
+=itme I<B>
+
+Change Block I/O statistics shown in Bytes <-> Requests
+
=item I<0> (number 0)
Show the normal list of domains display.
@@ -362,6 +370,10 @@ Sets script mode.
Sets stream mode.
+=item B<block-in-bytes> I<true|false>
+
+Show block device statistics in bytes.
+
=item B<end-time> I<time>
Set the time at which the program exits. See above for the
@@ -380,6 +392,12 @@ This is a bug and this behaviour may cha
=head1 NOTES
+=head2 Block I/O statistics
+
+This I/O value is the amount of I/O since the previous iteration
+of virt-top. To calculate speed of I/O, you should divide
+the number by delay secs.
+
=head2 NETWORK RX BYTES AND PACKETS
Libvirt/virt-top has no way to know that a packet transmitted to a
More information about the virt-tools-list
mailing list