Skip to contentSkip to conversation

block latency histogram

PATCH In review Vladimir Sementsov-Ogievskiy 3 participants 8 messages Mar 9, 2018 – Mar 12, 2018 Block layer

lore
Share & tools
lore
#0 lore raw

v6 cover block latency histogram

v6:

Use correct header qapi/qapi-builtin-types.h, to fix build again. Sorry for spam =(

v5:

Revert to v3 and just add qapi-types.h header.

v4:

Move block_latency_histogram_set from block/accounting.c to blockdev.c, as it uses qapi type uint64List and this fact breaks build.

v3:

- semantics, naming and wording changed a lot
- x prefixes added to new qapi names
- bug fixed about calculation of new_size (new_nbins now)
- drop g_renew
- in _clear() set nbinst to zero too

v2:

01: add block_latency_histogram_clear()
02: fix spelling (sorry =()
some rewordings
remove histogram if latency parameter unspecified

Vladimir Sementsov-Ogievskiy (2):
block/accounting: introduce latency histogram
qapi: add block latency histogram interface

 qapi/block-core.json       | 111 ++++++++++++++++++++++++++++++++++++++++++++-
 include/block/accounting.h |  35 ++++++++++++++
 block/accounting.c         |  91 +++++++++++++++++++++++++++++++++++++
 block/qapi.c               |  41 +++++++++++++++++
 blockdev.c                 |  43 ++++++++++++++++++
 5 files changed, 320 insertions(+), 1 deletion(-)
Signature · 1 line
2.11.1
#1 lore raw

PATCH v6 1/2 block/accounting: introduce latency histogram

Introduce latency histogram statics for block devices. For each accounted operation type latency region [0, +inf) is divided into subregions by several points. Then, calculate hits for each subregion.

---
 include/block/accounting.h | 35 ++++++++++++++++++
 block/accounting.c         | 91 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)
include/block/accounting.h +35 -0
index b833d26d6c..d1f67b10dd 100644
@@ -27,6 +27,7 @@
 
 #include "qemu/timed-average.h"
 #include "qemu/thread.h"
+#include "qapi/qapi-builtin-types.h"
 
 typedef struct BlockAcctTimedStats BlockAcctTimedStats;
 typedef struct BlockAcctStats BlockAcctStats;
@@ -45,6 +46,36 @@ struct BlockAcctTimedStats {
     QSLIST_ENTRY(BlockAcctTimedStats) entries;
 };
 
+typedef struct BlockLatencyHistogram {
+    /* The following histogram is represented like this:
+     *
+     * 5|           *
+     * 4|           *
+     * 3| *         *
+     * 2| *         *    *
+     * 1| *    *    *    *
+     *  +------------------
+     *      10   50   100
+     *
+     * BlockLatencyHistogram histogram = {
+     *     .nbins = 4,
+     *     .boundaries = {10, 50, 100},
+     *     .bins = {3, 1, 5, 2},
+     * };
+     *
+     * @boundaries array define histogram intervals as follows:
+     * [0, boundaries[0]), [boundaries[0], boundaries[1]), ...
+     * [boundaries[nbins-2], +inf)
+     *
+     * So, for example above, histogram intervals are:
+     * [0, 10), [10, 50), [50, 100), [100, +inf)
+     */
+    int nbins;
+    uint64_t *boundaries; /* @nbins-1 numbers here
+                             (all boundaries, except 0 and +inf) */
+    uint64_t *bins;
+} BlockLatencyHistogram;
+
 struct BlockAcctStats {
     QemuMutex lock;
     uint64_t nr_bytes[BLOCK_MAX_IOTYPE];
@@ -57,6 +88,7 @@ struct BlockAcctStats {
     QSLIST_HEAD(, BlockAcctTimedStats) intervals;
     bool account_invalid;
     bool account_failed;
+    BlockLatencyHistogram latency_histogram[BLOCK_MAX_IOTYPE];
 };
 
 typedef struct BlockAcctCookie {
@@ -82,5 +114,8 @@ void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
 int64_t block_acct_idle_time_ns(BlockAcctStats *stats);
 double block_acct_queue_depth(BlockAcctTimedStats *stats,
                               enum BlockAcctType type);
+int block_latency_histogram_set(BlockAcctStats *stats, enum BlockAcctType type,
+                                uint64List *boundaries);
+void block_latency_histograms_clear(BlockAcctStats *stats);
 
 #endif
block/accounting.c +91 -0

103 lines not on this page · raw message

Signature · 1 line
2.11.1
Reviewed-by on v6 1/2
#2 lore raw

Re: [Qemu-devel] [PATCH v6 1/2] block/accounting: introduce latency histogram

Quoted 2 lines · Vladimir Sementsov-Ogievskiy

Introduce latency histogram statics for block devices. For each accounted operation type latency region [0, +inf) is

Hard to read; I suggest: s/type latency/type, the latency/

Quoted 9 lines

divided into subregions by several points. Then, calculate hits for each subregion.

---
  include/block/accounting.h | 35 ++++++++++++++++++
  block/accounting.c         | 91 ++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 126 insertions(+)
Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
#3 lore raw

PATCH v6 2/2 qapi: add block latency histogram interface

In reply to Vladimir Sementsov-Ogievskiy

Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.

---
 qapi/block-core.json | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 block/qapi.c         |  41 +++++++++++++++++++
 blockdev.c           |  43 ++++++++++++++++++++
 3 files changed, 194 insertions(+), 1 deletion(-)
qapi/block-core.json +110 -1
index 00475f08d4..efe8fe92ff 100644
@@ -451,6 +451,106 @@
            'status': 'DirtyBitmapStatus'} }
 
 ##
+# @XBlockLatencyHistogramInfo:
+#
+# Block latency histogram.
+#
+# @boundaries: list of interval boundary values in nanoseconds, all greater
+#              than zero and in ascending order.
+#              For example, the list [10, 50, 100] produces the following
+#              histogram intervals: [0, 10), [10, 50), [50, 100), [100, +inf).
+#
+# @bins: list of io request counts corresponding to histogram intervals.
+#        len(@bins) = len(@boundaries) + 1
+#        For the example above, @bins may be something like [3, 1, 5, 2],
+#        and corresponding histogram looks like:
+#
+#        5|           *
+#        4|           *
+#        3| *         *
+#        2| *         *    *
+#        1| *    *    *    *
+#         +------------------
+#             10   50   100
+#
+# Since: 2.12
+##
+{ 'struct': 'XBlockLatencyHistogramInfo',
+  'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }
+
+##
+# @x-block-latency-histogram-set:
+#
+# Manage read, write and flush latency histograms for the device.
+#
+# If only @device parameter is specified, remove all present latency histograms
+# for the device. Otherwise, add/reset some of (or all) latency histograms.
+#
+# @device: device name to set latency histogram for.
+#
+# @boundaries: list of interval boundary values (see description in
+#              XBlockLatencyHistogramInfo definition). If specified, all
+#              latency histograms are removed, and empty ones created for all
+#              io types with intervals corresponding to @boundaries (except for
+#              io types, for which specific boundaries are set through the
+#              following parameters).
+#
+# @boundaries-read: list of interval boundary values for read latency
+#                   histogram. If specified, old read latency histogram is
+#                   removed, and empty one created with interavals
+#                   corresponding to @boundaries-read. The parameter has higher
+#                   priority then @boundaries.
+#
+# @boundaries-write: list of interaval boundary values for write latency
+#                    histogram.
+#
+# @boundaries-flush: list of interaval boundary values for flush latency
+#                    histogram.
+#
+# Returns: error if device is not found or @boundaries* arrays are invalid.
+#
+# Since: 2.12
+#
+# Example: set new histograms for all io types with intervals
+# [0, 10), [10, 50), [50, 100), [100, +inf):
+#
+# -> { "execute": "block-latency-histogram-set",
+#      "arguments": { "device": "drive0",
+#                     "boundaries": [10, 50, 100] } }
+# <- { "return": {} }
+#
+# Example: set new histogram only for write, other histograms will remain
+# not changed (or not created):
+#
+# -> { "execute": "block-latency-histogram-set",
+#      "arguments": { "device": "drive0",
+#                     "boundaries-write": [10, 50, 100] } }
+# <- { "return": {} }
+#
+# Example: set new histograms with the following intervals:
+#   read, flush: [0, 10), [10, 50), [50, 100), [100, +inf)
+#   write: [0, 1000), [1000, 5000), [5000, +inf)
+#
+# -> { "execute": "block-latency-histogram-set",
+#      "arguments": { "device": "drive0",
+#                     "boundaries": [10, 50, 100],
+#                     "boundaries-write": [1000, 5000] } }
+# <- { "return": {} }
+#
+# Example: remove all latency histograms:
+#
+# -> { "execute": "block-latency-histogram-set",
+#      "arguments": { "device": "drive0" } }
+# <- { "return": {} }
+##
+{ 'command': 'x-block-latency-histogram-set',
+  'data': {'device': 'str',
+           '*boundaries': ['uint64'],
+           '*boundaries-read': ['uint64'],
+           '*boundaries-write': ['uint64'],
+           '*boundaries-flush': ['uint64'] } }
+
+##
 # @BlockInfo:
 #
 # Block device information.  This structure describes a virtual device and
@@ -730,6 +830,12 @@
 # @timed_stats: Statistics specific to the set of previously defined
 #               intervals of time (Since 2.5)
 #
+# @x_rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)
+#
+# @x_wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)
+#
+# @x_flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)
+#
 # Since: 0.14.0
 ##
 { 'struct': 'BlockDeviceStats',
@@ -742,7 +848,10 @@
            'failed_flush_operations': 'int', 'invalid_rd_operations': 'int',
            'invalid_wr_operations': 'int', 'invalid_flush_operations': 'int',
            'account_invalid': 'bool', 'account_failed': 'bool',
-           'timed_stats': ['BlockDeviceTimedStats'] } }
+           'timed_stats': ['BlockDeviceTimedStats'],
+           '*x_rd_latency_histogram': 'XBlockLatencyHistogramInfo',
+           '*x_wr_latency_histogram': 'XBlockLatencyHistogramInfo',
+           '*x_flush_latency_histogram': 'XBlockLatencyHistogramInfo' } }
 
 ##
 # @BlockStats:
block/qapi.c +41 -0

53 lines not on this page · raw message

blockdev.c +43 -0

49 lines not on this page · raw message

Signature · 1 line
2.11.1
Reviewed-by on v6 2/2
#4 lore raw

Re: [Qemu-devel] [PATCH v6 2/2] qapi: add block latency histogram interface

Quoted 12 lines · Vladimir Sementsov-Ogievskiy

Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.

---
  qapi/block-core.json | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++-
  block/qapi.c         |  41 +++++++++++++++++++
  blockdev.c           |  43 ++++++++++++++++++++
  3 files changed, 194 insertions(+), 1 deletion(-)

qapi/block-core.json line 461

Quoted 4 lines
qapi/block-core.json +4 -0
+# @boundaries: list of interval boundary values in nanoseconds, all greater
+#              than zero and in ascending order.
+#              For example, the list [10, 50, 100] produces the following
+#              histogram intervals: [0, 10), [10, 50), [50, 100), [100, +inf).

10 vs. 50 nanoseconds is a bit unrealistic; the example makes sense but you may want to scale the boundaries into values that are more likely to make sense during use. Can be a followup.

Quoted 7 lines
qapi/block-core.json +7 -0
+#
+# @bins: list of io request counts corresponding to histogram intervals.
+#        len(@bins) = len(@boundaries) + 1
+#        For the example above, @bins may be something like [3, 1, 5, 2],
+#        and corresponding histogram looks like:
+#
+#        5|           *

qapi/block-core.json line 478

Quoted 10 lines
qapi/block-core.json +10 -0
+#        4|           *
+#        3| *         *
+#        2| *         *    *
+#        1| *    *    *    *
+#         +------------------
+#             10   50   100
+#
+# Since: 2.12
+##
+{ 'struct': 'XBlockLatencyHistogramInfo',

Struct names have no impact to introspection; I see no reason to use a leading X here.

qapi/block-core.json line 482

Quoted 4 lines
qapi/block-core.json +4 -0
+  'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }
+
+##
+# @x-block-latency-histogram-set:

I guess you've decided that this should be experimental in 2.12? If you want to change the name and promote it to a released interface, you don't have much time left.

qapi/block-core.json line 500

Quoted 4 lines
qapi/block-core.json +4 -0
+#
+# @boundaries-read: list of interval boundary values for read latency
+#                   histogram. If specified, old read latency histogram is
+#                   removed, and empty one created with interavals

s/interavals/intervals/

qapi/block-core.json line 504

Quoted 4 lines
qapi/block-core.json +4 -0
+#                   corresponding to @boundaries-read. The parameter has higher
+#                   priority then @boundaries.
+#
+# @boundaries-write: list of interaval boundary values for write latency

and again

qapi/block-core.json line 507

Quoted 3 lines
qapi/block-core.json +3 -0
+#                    histogram.
+#
+# @boundaries-flush: list of interaval boundary values for flush latency

copy-paste strikes again :)

qapi/block-core.json line 510

Quoted 3 lines
qapi/block-core.json +3 -0
+#                    histogram.
+#
+# Returns: error if device is not found or @boundaries* arrays are invalid.

s/@boundaries*/any boundary arrays/

qapi/block-core.json line 515

Quoted 5 lines
qapi/block-core.json +5 -0
+#
+# Since: 2.12
+#
+# Example: set new histograms for all io types with intervals
+# [0, 10), [10, 50), [50, 100), [100, +inf):

Again, are these reasonable numbers in nanoseconds? And spelling out the time unit in the example documentation may be helpful.

qapi/block-core.json line 833

Quoted 5 lines
qapi/block-core.json +1 -0
@@ -730,6 +830,12 @@
  # @timed_stats: Statistics specific to the set of previously defined
  #               intervals of time (Since 2.5)
  #
+# @x_rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)

Here, the naming makes sense (the _ is consistent with this being an older interface and already using it elsewhere, and the leading x matches with your command being marked experimental).

blockdev.c void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread, · line 4184

Quoted 7 lines
blockdev.c +3 -0
+++ b/blockdev.c
@@ -4180,6 +4180,49 @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,
      aio_context_release(old_context);
  }
 
+void qmp_x_block_latency_histogram_set(
+    const char *device,

I'll fix up the trivial typos, but you may want a followup patch.

Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
#5 lore raw

Re: [Qemu-devel] [PATCH v6 2/2] qapi: add block latency histogram interface

Quoted 14 lines · Eric Blake
Quoted 12 lines · Vladimir Sementsov-Ogievskiy

Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.

---
  qapi/block-core.json | 111
++++++++++++++++++++++++++++++++++++++++++++++++++-
  block/qapi.c         |  41 +++++++++++++++++++
  blockdev.c           |  43 ++++++++++++++++++++

  3 files changed, 194 insertions(+), 1 deletion(-)
Quoted 9 lines
Quoted 7 lines

+# @boundaries: list of interval boundary values in nanoseconds, all greater

(quoted diff) +2 -0
+#              than zero and in ascending order.
+#              For example, the list [10, 50, 100] produces the 

following
+#              histogram intervals: [0, 10), [10, 50), [50, 100), [100, +inf).

10 vs. 50 nanoseconds is a bit unrealistic; the example makes sense but you may want to scale the boundaries into values that are more likely to make sense during use.  Can be a followup.

I've just taken Paolo's suggestion), not realistic, but do not occupy so much space as mine. Be free to adjust it if you want

Quoted 23 lines
Quoted 10 lines
(quoted diff) +2 -0
+#
+# @bins: list of io request counts corresponding to histogram 

intervals.

(quoted diff) +2 -0
+#        len(@bins) = len(@boundaries) + 1
+#        For the example above, @bins may be something like [3, 1, 

5, 2],

qapi/block-core.json +3 -0
+#        and corresponding histogram looks like:
+#
+#        5|           *

qapi/block-core.json line 478

Quoted 10 lines
qapi/block-core.json +10 -0
+#        4|           *
+#        3| *         *
+#        2| *         *    *
+#        1| *    *    *    *
+#         +------------------
+#             10   50   100
+#
+# Since: 2.12
+##
+{ 'struct': 'XBlockLatencyHistogramInfo',

Struct names have no impact to introspection; I see no reason to use a leading X here.

Quoted 6 lines

qapi/block-core.json line 482

Quoted 4 lines

+  'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } }

qapi/block-core.json +3 -0
+
+##
+# @x-block-latency-histogram-set:

I guess you've decided that this should be experimental in 2.12? If you want to change the name and promote it to a released interface, you don't have much time left.

Yes. This is not random feature, it's required by our customers. And I understood (after I remake it to support different bins for different io types) that we are on the early stage of doing it, so it would be good to have it in 2.12 with x-.

Quoted 49 lines
Quoted 7 lines
qapi/block-core.json +3 -0
+#
+# @boundaries-read: list of interval boundary values for read latency
+#                   histogram. If specified, old read latency 

histogram is
+#                   removed, and empty one created with interavals

s/interavals/intervals/

Quoted 6 lines

+#                   corresponding to @boundaries-read. The parameter has higher

qapi/block-core.json +3 -0
+#                   priority then @boundaries.
+#
+# @boundaries-write: list of interaval boundary values for write 

latency

and again

Quoted 4 lines
qapi/block-core.json +3 -0
+#                    histogram.
+#
+# @boundaries-flush: list of interaval boundary values for flush 

latency

copy-paste strikes again :)

Quoted 4 lines
qapi/block-core.json +3 -0
+#                    histogram.
+#
+# Returns: error if device is not found or @boundaries* arrays are 

invalid.

s/@boundaries*/any boundary arrays/

qapi/block-core.json line 515

Quoted 5 lines
qapi/block-core.json +5 -0
+#
+# Since: 2.12
+#
+# Example: set new histograms for all io types with intervals
+# [0, 10), [10, 50), [50, 100), [100, +inf):

Again, are these reasonable numbers in nanoseconds?  And spelling out the time unit in the example documentation may be helpful.

qapi/block-core.json line 833

Quoted 5 lines
qapi/block-core.json +1 -0
@@ -730,6 +830,12 @@
   # @timed_stats: Statistics specific to the set of previously defined
   #               intervals of time (Since 2.5)
   #
+# @x_rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12)

Here, the naming makes sense (the _ is consistent with this being an older interface and already using it elsewhere, and the leading x matches with your command being marked experimental).

Quoted 8 lines
Quoted 7 lines
blockdev.c +1 -0
+++ b/blockdev.c
@@ -4180,6 +4180,49 @@ void qmp_x_blockdev_set_iothread(const char 
 *node_name, StrOrNull *iothread,
       aio_context_release(old_context);
   }

  +void qmp_x_block_latency_histogram_set(
+    const char *device,

I'll fix up the trivial typos, but you may want a followup patch.

Thank you!

Quoted 3 lines
Signature · 2 lines
Best regards,
Vladimir
#6 lore raw
In reply to Vladimir Sementsov-Ogievskiy
Quoted 10 lines · Vladimir Sementsov-Ogievskiy

v6:

Use correct header qapi/qapi-builtin-types.h, to fix build again. Sorry for spam =(

Vladimir Sementsov-Ogievskiy (2):
block/accounting: introduce latency histogram
qapi: add block latency histogram interface

This touches both block and QAPI, but I've gone ahead and queued it on the QAPI tree. Not much time left if you want to drop the x- prefix and make this interface officially supported for 2.12. Queued:

git://repo.or.cz/qemu/ericb.git qapi
http://repo.or.cz/qemu/ericb.git/shortlog/refs/heads/qapi

I'll send a PULL request for my QAPI tree as my first act on Monday.

Quoted 8 lines
  qapi/block-core.json       | 111 ++++++++++++++++++++++++++++++++++++++++++++-
  include/block/accounting.h |  35 ++++++++++++++
  block/accounting.c         |  91 +++++++++++++++++++++++++++++++++++++
  block/qapi.c               |  41 +++++++++++++++++
  blockdev.c                 |  43 ++++++++++++++++++
  5 files changed, 320 insertions(+), 1 deletion(-)
Signature · 3 lines
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org
Reviewed-by on the v6 series
#7 lore raw
In reply to Vladimir Sementsov-Ogievskiy
Quoted 37 lines · Vladimir Sementsov-Ogievskiy

v6:

Use correct header qapi/qapi-builtin-types.h, to fix build again. Sorry for spam =(

v5:

Revert to v3 and just add qapi-types.h header.

v4:

Move block_latency_histogram_set from block/accounting.c to blockdev.c, as it uses qapi type uint64List and this fact breaks build.

v3:

- semantics, naming and wording changed a lot
- x prefixes added to new qapi names
- bug fixed about calculation of new_size (new_nbins now)
- drop g_renew
- in _clear() set nbinst to zero too

v2:

01: add block_latency_histogram_clear()
02: fix spelling (sorry =()
some rewordings
remove histogram if latency parameter unspecified

Vladimir Sementsov-Ogievskiy (2):
block/accounting: introduce latency histogram
qapi: add block latency histogram interface

Quoted 11 lines
 qapi/block-core.json       | 111 ++++++++++++++++++++++++++++++++++++++++++++-
 include/block/accounting.h |  35 ++++++++++++++
 block/accounting.c         |  91 +++++++++++++++++++++++++++++++++++++
 block/qapi.c               |  41 +++++++++++++++++
 blockdev.c                 |  43 ++++++++++++++++++
 5 files changed, 320 insertions(+), 1 deletion(-)
Signature · 1 line
2.11.1