Add --block-in-bytes option.
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Wed, 2 Feb 2011 14:38:47 +0000 (14:38 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Wed, 2 Feb 2011 14:40:57 +0000 (14:40 +0000)
This option and the 'B' key toggles block I/O stats between
requests and bytes.

virt-top/virt-top.pod
virt-top/virt_top.ml

index 9e1e228..3a955ac 100755 (executable)
@@ -158,6 +158,10 @@ when used together with the I<--csv> and I<-n> options.
 Stream mode.  All output is sent to stdout.  This can be used from
 shell scripts etc.  There is no user interface.
 
 Stream mode.  All output is sent to stdout.  This can be used from
 shell scripts etc.  There is 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.
 =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.
 
 
 Change the delay between screen updates.
 
+=item I<B>
+
+Toggle Block I/O statistics so they are shown in either bytes or requests.
+
 =item I<0> (number 0)
 
 Show the normal list of domains display.
 =item I<0> (number 0)
 
 Show the normal list of domains display.
@@ -362,6 +370,10 @@ Sets script mode.
 
 Sets stream 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
 =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 change in the future.
 
 =head1 NOTES
 
 
 =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
 =head2 NETWORK RX BYTES AND PACKETS
 
 Libvirt/virt-top has no way to know that a packet transmitted to a
index 75042c1..5030165 100644 (file)
@@ -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 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 =
 
 (* 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)";
       " " ^ 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
     "--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
       | _, "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, _ ->
       | _, "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. *)
   (* 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. *)
 }
   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_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
                      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
              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;
 
            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
            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;
 
         (* 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
         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
           | (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
                 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 []) @
       (* 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 [])
   )
 
     (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_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;
         ] else []) @
        (if !csv_net then [
           string_of_int64_option rd.rd_net_rx_bytes;
@@ -1283,7 +1315,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 *)
     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 =
   (* sort by ID *)
   let doms =
     let compare =
@@ -1300,10 +1335,10 @@ let dump_stdout
   let dump_domain = fun name rd
   -> begin
     let state = show_state rd.rd_info.D.state in
   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"
     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"
@@ -1401,6 +1436,7 @@ and get_key_press setup delay =
     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 '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
   )
 
     else unknown_command k
   )
 
@@ -1546,6 +1582,12 @@ and toggle_block_display () =            (* key 3 *)
     | TaskDisplay | NetDisplay -> BlockDisplay
     | BlockDisplay -> TaskDisplay
 
     | 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
 (* Write an init file. *)
 and write_init_file () =
   match !init_file with
@@ -1674,6 +1716,7 @@ and show_help (_, _, _, _, _, _, hostname,
   key "q"        (s_"Quit");
   key "d s"      (s_"Set update interval");
   key "h"        (s_"Help");
   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 ());
 
   (* Sort order. *)
   ignore (get_lineno ());