[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