block latency histogram
cover block latency histogram
Vladimir Sementsov-Ogievskiy (2):
block/accounting: introduce latency histogram
qapi: add block latency histogram interface
qapi/block-core.json | 62 +++++++++++++++++++++++++++++++++- include/block/accounting.h | 8 +++++ block/accounting.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ block/qapi.c | 31 +++++++++++++++++ blockdev.c | 15 +++++++++ 5 files changed, 198 insertions(+), 1 deletion(-)
Signature · 1 line
2.11.1
PATCH 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 | 8 +++++ block/accounting.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+)
include/block/accounting.h +8 -0
@@ -45,6 +45,12 @@ struct BlockAcctTimedStats {QSLIST_ENTRY (BlockAcctTimedStats) entries; }; +typedef struct BlockLatencyHistogram { +int size; +uint64_t *points;/* @size-1 points here (all points, except 0 and +inf) */ +uint64_t *histogram[BLOCK_MAX_IOTYPE ];/* @size elements for each type */ +}BlockLatencyHistogram ; +struct BlockAcctStats {QemuMutex lock;uint64_t nr_bytes[BLOCK_MAX_IOTYPE ];
@@ -57,6 +63,7 @@ struct BlockAcctStats { QSLIST_HEAD(, BlockAcctTimedStats) intervals;bool account_invalid;bool account_failed; +BlockLatencyHistogram latency_histogram; }; typedef struct BlockAcctCookie {
@@ -82,5 +89,6 @@ 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,uint64List *latency);#endif
block/accounting.c +83 -0
95 lines not on this page · raw message
Signature · 1 line
2.11.1
PATCH 2/2 qapi: add block latency histogram interface
In reply to Vladimir Sementsov-OgievskiySet (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.
--- qapi/block-core.json | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++- block/qapi.c | 31 ++++++++++++++++++++++++++ blockdev.c | 15 +++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-)
qapi/block-core.json +61 -1
@@ -451,6 +451,63 @@ 'status': 'DirtyBitmapStatus'} } ## +# @BlockLatencyHistogramInfo: +# +# Block latency histogram. +# +# @latency: list of latency points in microseconds. Equals to @latency parameter +# of last called block-latency-histogram-set. +# +# @read: list of read-request counts corresponding to latency region. +# len(@read) = len(@latency) + 1 +# @read[0] corresponds to latency region [0, @latency[0]) +# for 0 < i < len(@latency): @read[i] corresponds to latency region +# [@latency[i-1], @latency[i]) +# @read.last_element corresponds to latency region +# [@latency.last_element, +inf) +# +# @write: list of write-request counts (see @read semantics) +# +# @flush: list of flush-request counts (see @read semantics) +# +# Since: 2.12 +## +{ 'struct': 'BlockLatencyHistogramInfo', + 'data': {'latency': ['uint64'], + 'read': ['uint64'], + 'write': ['uint64'], + 'flush': ['uint64'] } } + +## +# @block-latency-histogram-set: +# +# Add latency histogram to block device. If latency histogram alredy exists for +# the device it will be removed and a new one created. Latency histogram may be +# quered through query-blockstats. +# +# @device: device name to set latency histogram for. +# +# @latency: list of latency points in microseconds. The sequcence must be +# ascending, elements must be greater than zero. Histogram latency +# regions would be +# [0, @latency[0]), ..., [@latency[i], @latency[i+1]), ..., +# [@latency.last_element, +inf) +# +# Returns: error if device is not found. +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "device": "drive0", +# "latency": [500000, 1000000, 2000000] } } +# <- { "return": {} } +## +{ 'command': 'block-latency-histogram-set', + 'data': {'device': 'str', 'latency': ['uint64'] } } + +## # @BlockInfo: # # Block device information. This structure describes a virtual device and
@@ -730,6 +787,8 @@ # @timed_stats: Statistics specific to the set of previously defined # intervals of time (Since 2.5) # +# @latency-histogram: @BlockLatencyHistogramInfo. (Since 2.12) +# # Since: 0.14.0 ## { 'struct': 'BlockDeviceStats',
@@ -742,7 +801,8 @@ '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'], + '*latency-histogram': 'BlockLatencyHistogramInfo' } } ## # @BlockStats:
block/qapi.c +31 -0
@@ -389,6 +389,24 @@ static void bdrv_query_info(BlockBackend *blk, BlockInfo **p_info,qapi_free_BlockInfo (info); } +static uint64List *uint64_list (uint64_t *list,int size) +{ +int i; +uint64List *out_list =NULL ; +uint64List **pout_list = &out_list; + +for (i =0 ; i < size; i++) { +uint64List *entry =g_new (uint64List,1 ); + entry->value = list[i]; + *pout_list = entry; + pout_list = &entry->next; + } + + *pout_list =NULL ; + +return out_list; +} +static void bdrv_query_blk_stats (BlockDeviceStats *ds,BlockBackend *blk) {BlockAcctStats *stats =blk_get_stats (blk);
@@ -454,6 +472,19 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk) dev_stats->avg_wr_queue_depth =block_acct_queue_depth (ts,BLOCK_ACCT_WRITE ); } + + ds->has_latency_histogram = stats->latency_histogram.points !=NULL ; +if (ds->has_latency_histogram) { +BlockLatencyHistogramInfo *info =g_new0 (BlockLatencyHistogramInfo,1 ); +BlockLatencyHistogram *h = &stats->latency_histogram; + + ds->latency_histogram = info; + + info->latency =uint64_list (h->points, h->size -1 ); + info->read =uint64_list (h->histogram[BLOCK_ACCT_READ ], h->size); + info->write =uint64_list (h->histogram[BLOCK_ACCT_WRITE ], h->size); + info->flush =uint64_list (h->histogram[BLOCK_ACCT_FLUSH ], h->size); + } } static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs,
blockdev.c +15 -0
@@ -4176,6 +4176,21 @@ void qmp_x_blockdev_set_iothread(const char *node_name, StrOrNull *iothread,aio_context_release (old_context); } +void qmp_block_latency_histogram_set (const char *device,uint64List *latency, +Error **errp) +{ +BlockBackend *blk =blk_by_name (device); +if (!blk) { +error_setg (errp,"Device '%s' not found" , device); +return ; + } + +if (block_latency_histogram_set (blk_get_stats (blk), latency) <0 ) { +error_setg (errp,"Invalid latency array" ); +return ; + } +} +QemuOptsList qemu_common_drive_opts = { .name ="drive" , .head =QTAILQ_HEAD_INITIALIZER (qemu_common_drive_opts.head),
Signature · 1 line
2.11.1
Re: [Qemu-devel] [PATCH 2/2] qapi: add block latency histogram interface
Quoted 16 lines · Vladimir Sementsov-Ogievskiy
Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.
Signed-off-by Vladimir Sementsov-Ogievskiy <[email protected]>--- qapi/block-core.json | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++- block/qapi.c | 31 ++++++++++++++++++++++++++ blockdev.c | 15 +++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-)qapi/block-core.json +0
-0
qapi/block-core.json line 459
Quoted 9 lines
qapi/block-core.json +6
-0@@ -451,6 +451,63 @@ 'status': 'DirtyBitmapStatus'} } ## +# @BlockLatencyHistogramInfo: +# +# Block latency histogram. +# +# @latency: list of latency points in microseconds. Equals to @latency parameter +# of last called block-latency-histogram-set.
Second sentence might read better as:
Matches the @latency parameter from the last call to block-latency-histogram-set for the given device.
Quoted 10 lines
qapi/block-core.json +10
-0+# +# @read: list of read-request counts corresponding to latency region. +# len(@read) = len(@latency) + 1 +# @read[0] corresponds to latency region [0, @latency[0]) +# for 0 < i < len(@latency): @read[i] corresponds to latency region +# [@latency[i-1], @latency[i]) +# @read.last_element corresponds to latency region +# [@latency.last_element, +inf) +# +# @write: list of write-request counts (see @read semantics)
qapi/block-core.json line 479
Quoted 10 lines
qapi/block-core.json +10
-0+# +# @flush: list of flush-request counts (see @read semantics) +# +# Since: 2.12 +## +{ 'struct': 'BlockLatencyHistogramInfo', + 'data': {'latency': ['uint64'], + 'read': ['uint64'], + 'write': ['uint64'], + 'flush': ['uint64'] } }
Okay, I can see how this interface works.
qapi/block-core.json line 484
Quoted 5 lines
qapi/block-core.json +5
-0+ +## +# @block-latency-histogram-set: +# +# Add latency histogram to block device. If latency histogram alredy exists for
s/latency/a latency/ (twice)
s/alredy/already/
qapi/block-core.json line 485
Quoted 1 line
qapi/block-core.json +1
-0+# the device it will be removed and a new one created. Latency histogram may be
s/Latency/The latency/
qapi/block-core.json line 486
Quoted 1 line
qapi/block-core.json +1
-0+# quered through query-blockstats.
s/quered/queried/
qapi/block-core.json line 490
Quoted 4 lines
qapi/block-core.json +4
-0+# +# @device: device name to set latency histogram for. +# +# @latency: list of latency points in microseconds. The sequcence must be
s/sequcence/sequence/
Quoted 8 lines
qapi/block-core.json +8
-0+# ascending, elements must be greater than zero. Histogram latency +# regions would be +# [0, @latency[0]), ..., [@latency[i], @latency[i+1]), ..., +# [@latency.last_element, +inf) +# +# Returns: error if device is not found. +# +# Since: 2.12
qapi/block-core.json line 508
Quoted 10 lines
qapi/block-core.json +10
-0+# +# Example: +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "device": "drive0", +# "latency": [500000, 1000000, 2000000] } } +# <- { "return": {} } +## +{ 'command': 'block-latency-histogram-set', + 'data': {'device': 'str', 'latency': ['uint64'] } }
The commit message mentioned that you can set and clear histogram tracking; how does this interface let you clear things? By passing a 0-length latency array? If you violate the constraint (pass non-ascending points, for example), does the previous latency map get wiped out or is it still preserved unchanged?
qapi/block-core.json line 790
Quoted 10 lines
qapi/block-core.json +3
-0+ +## # @BlockInfo: # # Block device information. This structure describes a virtual device and@@ -730,6 +787,8 @@ # @timed_stats: Statistics specific to the set of previously defined # intervals of time (Since 2.5) # +# @latency-histogram: @BlockLatencyHistogramInfo. (Since 2.12)
I'd mention that this only appears if block-latency-histogram-set has been called.
Quoted 12 lines
qapi/block-core.json +3
-1+# # Since: 0.14.0 ## { 'struct': 'BlockDeviceStats',@@ -742,7 +801,8 @@ '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'], + '*latency-histogram': 'BlockLatencyHistogramInfo' } }
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [Qemu-devel] [PATCH 2/2] qapi: add block latency histogram interface
Quoted 96 lines · Eric Blake
Quoted 24 lines · Vladimir Sementsov-Ogievskiy
Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.
Signed-off-by Vladimir Sementsov-Ogievskiy <[email protected]>---
qapi/block-core.json| 62
+++++++++++++++++++++++++++++++++++++++++++++++++++-
block/qapi.c | 31 ++++++++++++++++++++++++++ blockdev.c | 15 +++++++++++++3 files changed, 107 insertions(+), 1 deletion(-)qapi/block-core.json +5
-0@@ -451,6 +451,63 @@ 'status': 'DirtyBitmapStatus'} } ## +# @BlockLatencyHistogramInfo: +# +# Block latency histogram. +# +# @latency: list of latency points in microseconds. Equals toQuoted 2 lines
@latency parameter
+# of last called block-latency-histogram-set.Second sentence might read better as:
Matches the @latency parameter from the last call to block-latency-histogram-set for the given device.
Quoted 11 lines
qapi/block-core.json +5
-0+# +# @read: list of read-request counts corresponding to latency region. +# len(@read) = len(@latency) + 1 +# @read[0] corresponds to latency region [0, @latency[0]) +# for 0 < i < len(@latency): @read[i] corresponds to latencyregion
qapi/block-core.json +5
-0+# [@latency[i-1], @latency[i]) +# @read.last_element corresponds to latency region +# [@latency.last_element, +inf) +# +# @write: list of write-request counts (see @read semantics)qapi/block-core.json line 479
Quoted 10 lines
qapi/block-core.json +10
-0+# +# @flush: list of flush-request counts (see @read semantics) +# +# Since: 2.12 +## +{ 'struct': 'BlockLatencyHistogramInfo', + 'data': {'latency': ['uint64'], + 'read': ['uint64'], + 'write': ['uint64'], + 'flush': ['uint64'] } }Okay, I can see how this interface works.
Quoted 6 lines
qapi/block-core.json +5
-0+ +## +# @block-latency-histogram-set: +# +# Add latency histogram to block device. If latency histogram alredyexists for
s/latency/a latency/ (twice)
s/alredy/already/Quoted 2 lines
+# the device it will be removed and a new one created. Latency histogram may be
s/Latency/The latency/
Quoted 1 line
+# quered through query-blockstats.
s/quered/queried/
Quoted 5 lines
qapi/block-core.json +4
-0+# +# @device: device name to set latency histogram for. +# +# @latency: list of latency points in microseconds. The sequcencemust be
s/sequcence/sequence/
Quoted 13 lines
+# ascending, elements must be greater than zero. Histogram latency
qapi/block-core.json +11
-0+# regions would be +# [0, @latency[0]), ..., [@latency[i], @latency[i+1]), ..., +# [@latency.last_element, +inf) +# +# Returns: error if device is not found. +# +# Since: 2.12 +# +# Example: +# +# -> { "execute": "block-latency-histogram-set",
Quoted 8 lines
qapi/block-core.json line 508
Quoted 6 lines
qapi/block-core.json +6
-0+# "arguments": { "device": "drive0", +# "latency": [500000, 1000000, 2000000] } } +# <- { "return": {} } +## +{ 'command': 'block-latency-histogram-set', + 'data': {'device': 'str', 'latency': ['uint64'] } }The commit message mentioned that you can set and clear histogram tracking; how does this interface let you clear things? By passing a 0-length latency array? If you violate the constraint (pass non-ascending points, for example), does the previous latency map get wiped out or is it still preserved unchanged?
On error nothing is changed.
By "clear" I mean zeroing statistics, not removing the whole histogram. And to zero statistics you can call set with the same latency array. There is no way to remove histogram at all.. We can add block-latency-histogram-unset later if needed.
Quoted 13 lines
qapi/block-core.json line 790
Quoted 11 lines
qapi/block-core.json +2
-0+ +### @BlockInfo:
#
# Block device information. This structure describes a virtual device andqapi/block-core.json +1
-0@@ -730,6 +787,8 @@ # @timed_stats: Statistics specific to the set of previously defined # intervals of time (Since 2.5) # +# @latency-histogram: @BlockLatencyHistogramInfo. (Since 2.12)I'd mention that this only appears if block-latency-histogram-set has been called.
yes
Quoted 14 lines
Quoted 12 lines
qapi/block-core.json +3
-1+# # Since: 0.14.0 ## { 'struct': 'BlockDeviceStats',@@ -742,7 +801,8 @@ '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'], + '*latency-histogram': 'BlockLatencyHistogramInfo' } }
Signature · 2 lines
Best regards, Vladimir
Re: [Qemu-devel] [PATCH 2/2] qapi: add block latency histogram interface
Quoted 7 lines · Vladimir Sementsov-Ogievskiy
Quoted 6 lines · Eric Blake
Quoted 4 lines · Vladimir Sementsov-Ogievskiy
Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.
Quoted 6 lines
Quoted 1 line
The commit message mentioned that you can set and clear histogram tracking; how does this interface let you clear things? By passing a 0-length latency array? If you violate the constraint (pass non-ascending points, for example), does the previous latency map get wiped out or is it still preserved unchanged?
On error nothing is changed.
By "clear" I mean zeroing statistics, not removing the whole histogram. And to zero statistics you can call set with the same latency array. There is no way to remove histogram at all.. We can add block-latency-histogram-unset later if needed.
Maybe "set (or restart) histogram collection points" might read better? I also don't think we need a new command; if you make 'latency' optional, then omitting it can serve to stop collecting statistics altogether, without needing a new command (then again, if you do that, now the command is used to "set, restart, and clear histogram collection").
Signature · 3 lines
Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3266 Virtualization: qemu.org | libvirt.org
Re: [Qemu-devel] [PATCH 2/2] qapi: add block latency histogram interface
Quoted 8 lines · Eric Blake
Quoted 7 lines · Vladimir Sementsov-Ogievskiy
Quoted 6 lines · Eric Blake
Quoted 4 lines · Vladimir Sementsov-Ogievskiy
Set (and clear) histogram through new command block-latency-histogram-set and show new statistics in query-blockstats results.
Quoted 9 lines
Quoted 6 lines
Quoted 1 line
The commit message mentioned that you can set and clear histogram tracking; how does this interface let you clear things? By passing a 0-length latency array? If you violate the constraint (pass non-ascending points, for example), does the previous latency map get wiped out or is it still preserved unchanged?
On error nothing is changed.
By "clear" I mean zeroing statistics, not removing the whole histogram. And to zero statistics you can call set with the same latency array. There is no way to remove histogram at all.. We can add block-latency-histogram-unset later if needed.
Maybe "set (or restart) histogram collection points" might read better? I also don't think we need a new command; if you make 'latency' optional, then omitting it can serve to stop collecting statistics altogether, without needing a new command (then again, if you do that, now the command is used to "set, restart, and clear histogram collection").
I like the idea, will do.
Signature · 2 lines
Best regards, Vladimir