diff mbox

[3/3] block: latency accounting

Message ID 20110825062610.GC30639@lst.de
State New
Headers show

Commit Message

Christoph Hellwig Aug. 25, 2011, 6:26 a.m. UTC
Account the total latency for read/write/flush requests.  This allows
management tools to average it based on a snapshot of the nr ops
counters and allow checking for SLAs or provide statistics.

Signed-off-by: Christoph Hellwig <hch@lst.de>

Comments

Kevin Wolf Aug. 26, 2011, 1:05 p.m. UTC | #1
Am 25.08.2011 08:26, schrieb Christoph Hellwig:
> Account the total latency for read/write/flush requests.  This allows
> management tools to average it based on a snapshot of the nr ops
> counters and allow checking for SLAs or provide statistics.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> 
> Index: qemu/block.c
> ===================================================================
> --- qemu.orig/block.c	2011-08-25 08:01:12.000000000 +0200
> +++ qemu/block.c	2011-08-25 08:03:02.908005646 +0200
> @@ -1889,12 +1889,18 @@ static void bdrv_stats_iter(QObject *dat
>                          " rd_operations=%" PRId64
>                          " wr_operations=%" PRId64
>                          " flush_operations=%" PRId64
> +                        " wr_total_time_ns=%" PRId64
> +                        " rd_total_time_ns=%" PRId64
> +                        " flush_total_time_ns=%" PRId64
>                          "\n",
>                          qdict_get_int(qdict, "rd_bytes"),
>                          qdict_get_int(qdict, "wr_bytes"),
>                          qdict_get_int(qdict, "rd_operations"),
>                          qdict_get_int(qdict, "wr_operations"),
> -                        qdict_get_int(qdict, "flush_operations"));
> +                        qdict_get_int(qdict, "flush_operations"),
> +                        qdict_get_int(qdict, "wr_total_time_ns"),
> +                        qdict_get_int(qdict, "rd_total_time_ns"),
> +                        qdict_get_int(qdict, "flush_total_time_ns"));
>  }
>  
>  void bdrv_stats_print(Monitor *mon, const QObject *data)
> @@ -1913,7 +1919,10 @@ static QObject* bdrv_info_stats_bs(Block
>                               "'rd_operations': %" PRId64 ","
>                               "'wr_operations': %" PRId64 ","
>                               "'wr_highest_offset': %" PRId64 ","
> -                             "'flush_operations': %" PRId64
> +                             "'flush_operations': %" PRId64 ","
> +                             "'wr_total_time_ns': %" PRId64 ","
> +                             "'rd_total_time_ns': %" PRId64 ","
> +                             "'flush_total_time_ns': %" PRId64
>                               "} }",
>                               bs->nr_bytes[BDRV_ACCT_READ],
>                               bs->nr_bytes[BDRV_ACCT_WRITE],
> @@ -1921,7 +1930,10 @@ static QObject* bdrv_info_stats_bs(Block
>                               bs->nr_ops[BDRV_ACCT_WRITE],
>                               bs->wr_highest_sector *
>                               (uint64_t)BDRV_SECTOR_SIZE,
> -                             bs->nr_ops[BDRV_ACCT_FLUSH]);
> +                             bs->nr_ops[BDRV_ACCT_FLUSH],
> +                             bs->total_time_ns[BDRV_ACCT_READ],
> +                             bs->total_time_ns[BDRV_ACCT_WRITE],
> +                             bs->total_time_ns[BDRV_ACCT_FLUSH]);

The order of READ vs. WRITE is wrong here, so read latencies show up as
wr_total_time. I can fix it locally if you agree that swapping the two
lines is the right fix.

Kevin
Christoph Hellwig Aug. 26, 2011, 4:06 p.m. UTC | #2
On Fri, Aug 26, 2011 at 03:05:06PM +0200, Kevin Wolf wrote:
> The order of READ vs. WRITE is wrong here, so read latencies show up as
> wr_total_time. I can fix it locally if you agree that swapping the two
> lines is the right fix.

Yes, it got mixed up in one of the revamps.
diff mbox

Patch

Index: qemu/block.c
===================================================================
--- qemu.orig/block.c	2011-08-25 08:01:12.000000000 +0200
+++ qemu/block.c	2011-08-25 08:03:02.908005646 +0200
@@ -1889,12 +1889,18 @@  static void bdrv_stats_iter(QObject *dat
                         " rd_operations=%" PRId64
                         " wr_operations=%" PRId64
                         " flush_operations=%" PRId64
+                        " wr_total_time_ns=%" PRId64
+                        " rd_total_time_ns=%" PRId64
+                        " flush_total_time_ns=%" PRId64
                         "\n",
                         qdict_get_int(qdict, "rd_bytes"),
                         qdict_get_int(qdict, "wr_bytes"),
                         qdict_get_int(qdict, "rd_operations"),
                         qdict_get_int(qdict, "wr_operations"),
-                        qdict_get_int(qdict, "flush_operations"));
+                        qdict_get_int(qdict, "flush_operations"),
+                        qdict_get_int(qdict, "wr_total_time_ns"),
+                        qdict_get_int(qdict, "rd_total_time_ns"),
+                        qdict_get_int(qdict, "flush_total_time_ns"));
 }
 
 void bdrv_stats_print(Monitor *mon, const QObject *data)
@@ -1913,7 +1919,10 @@  static QObject* bdrv_info_stats_bs(Block
                              "'rd_operations': %" PRId64 ","
                              "'wr_operations': %" PRId64 ","
                              "'wr_highest_offset': %" PRId64 ","
-                             "'flush_operations': %" PRId64
+                             "'flush_operations': %" PRId64 ","
+                             "'wr_total_time_ns': %" PRId64 ","
+                             "'rd_total_time_ns': %" PRId64 ","
+                             "'flush_total_time_ns': %" PRId64
                              "} }",
                              bs->nr_bytes[BDRV_ACCT_READ],
                              bs->nr_bytes[BDRV_ACCT_WRITE],
@@ -1921,7 +1930,10 @@  static QObject* bdrv_info_stats_bs(Block
                              bs->nr_ops[BDRV_ACCT_WRITE],
                              bs->wr_highest_sector *
                              (uint64_t)BDRV_SECTOR_SIZE,
-                             bs->nr_ops[BDRV_ACCT_FLUSH]);
+                             bs->nr_ops[BDRV_ACCT_FLUSH],
+                             bs->total_time_ns[BDRV_ACCT_READ],
+                             bs->total_time_ns[BDRV_ACCT_WRITE],
+                             bs->total_time_ns[BDRV_ACCT_FLUSH]);
     dict  = qobject_to_qdict(res);
 
     if (*bs->device_name) {
@@ -3133,6 +3145,7 @@  bdrv_acct_start(BlockDriverState *bs, Bl
     assert(type < BDRV_MAX_IOTYPE);
 
     cookie->bytes = bytes;
+    cookie->start_time_ns = get_clock();
     cookie->type = type;
 }
 
@@ -3143,6 +3156,7 @@  bdrv_acct_done(BlockDriverState *bs, Blo
 
     bs->nr_bytes[cookie->type] += cookie->bytes;
     bs->nr_ops[cookie->type]++;
+    bs->total_time_ns[cookie->type] += get_clock() - cookie->start_time_ns;
 }
 
 int bdrv_img_create(const char *filename, const char *fmt,
Index: qemu/block_int.h
===================================================================
--- qemu.orig/block_int.h	2011-08-25 08:01:12.000000000 +0200
+++ qemu/block_int.h	2011-08-25 08:02:20.981566114 +0200
@@ -28,6 +28,7 @@ 
 #include "qemu-option.h"
 #include "qemu-queue.h"
 #include "qemu-coroutine.h"
+#include "qemu-timer.h"
 
 #define BLOCK_FLAG_ENCRYPT	1
 #define BLOCK_FLAG_COMPAT6	4
@@ -186,6 +187,7 @@  struct BlockDriverState {
     /* I/O stats (display with "info blockstats"). */
     uint64_t nr_bytes[BDRV_MAX_IOTYPE];
     uint64_t nr_ops[BDRV_MAX_IOTYPE];
+    uint64_t total_time_ns[BDRV_MAX_IOTYPE];
     uint64_t wr_highest_sector;
 
     /* Whether the disk can expand beyond total_sectors */
Index: qemu/qmp-commands.hx
===================================================================
--- qemu.orig/qmp-commands.hx	2011-08-25 08:01:04.000000000 +0200
+++ qemu/qmp-commands.hx	2011-08-25 08:02:20.984899429 +0200
@@ -1202,6 +1202,9 @@  Each json-object contain the following:
     - "rd_operations": read operations (json-int)
     - "wr_operations": write operations (json-int)
     - "flush_operations": cache flush operations (json-int)
+    - "wr_total_time_ns": total time spend on writes in nano-seconds (json-int)
+    - "rd_total_time_ns": total time spend on reads in nano-seconds (json-int)
+    - "flush_total_time_ns": total time spend on cache flushes in nano-seconds (json-int)
     - "wr_highest_offset": Highest offset of a sector written since the
                            BlockDriverState has been opened (json-int)
 - "parent": Contains recursively the statistics of the underlying
@@ -1223,6 +1226,9 @@  Example:
                   "wr_operations":751,
                   "rd_bytes":122567168,
                   "rd_operations":36772
+                  "wr_total_times_ns":313253456
+                  "rd_total_times_ns":3465673657
+                  "flush_total_times_ns":49653
                   "flush_operations":61,
                }
             },
@@ -1233,6 +1239,9 @@  Example:
                "rd_bytes":122739200,
                "rd_operations":36604
                "flush_operations":51,
+               "wr_total_times_ns":313253456
+               "rd_total_times_ns":3465673657
+               "flush_total_times_ns":49653
             }
          },
          {
@@ -1244,6 +1253,9 @@  Example:
                "rd_bytes":0,
                "rd_operations":0
                "flush_operations":0,
+               "wr_total_times_ns":0
+               "rd_total_times_ns":0
+               "flush_total_times_ns":0
             }
          },
          {
@@ -1255,6 +1267,9 @@  Example:
                "rd_bytes":0,
                "rd_operations":0
                "flush_operations":0,
+               "wr_total_times_ns":0
+               "rd_total_times_ns":0
+               "flush_total_times_ns":0
             }
          },
          {
@@ -1266,6 +1281,9 @@  Example:
                "rd_bytes":0,
                "rd_operations":0
                "flush_operations":0,
+               "wr_total_times_ns":0
+               "rd_total_times_ns":0
+               "flush_total_times_ns":0
             }
          }
       ]
Index: qemu/block.h
===================================================================
--- qemu.orig/block.h	2011-08-25 08:02:32.094839241 +0200
+++ qemu/block.h	2011-08-25 08:02:40.718125859 +0200
@@ -263,6 +263,7 @@  enum BlockAcctType {
 
 typedef struct BlockAcctCookie {
     int64_t bytes;
+    int64_t start_time_ns;
     enum BlockAcctType type;
 } BlockAcctCookie;