From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: qemu-devel@nongnu.org, qemu-block@nongnu.org
Cc: eblake@redhat.com, armbru@redhat.com, mreitz@redhat.com,
kwolf@redhat.com, den@openvz.org, nshirokovskiy@virtuozzo.com,
vsementsov@virtuozzo.com
Subject: [Qemu-devel] [PATCH v2 1/2] block/accounting: introduce latency histogram
Date: Wed, 7 Feb 2018 15:50:36 +0300 [thread overview]
Message-ID: <20180207125037.13510-2-vsementsov@virtuozzo.com> (raw)
In-Reply-To: <20180207125037.13510-1-vsementsov@virtuozzo.com>
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.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
---
include/block/accounting.h | 9 +++++
block/accounting.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 106 insertions(+)
diff --git a/include/block/accounting.h b/include/block/accounting.h
index b833d26d6c..9679020f64 100644
--- a/include/block/accounting.h
+++ b/include/block/accounting.h
@@ -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,7 @@ 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);
+void block_latency_histogram_clear(BlockAcctStats *stats);
#endif
diff --git a/block/accounting.c b/block/accounting.c
index 87ef5bbfaa..0051ff0c24 100644
--- a/block/accounting.c
+++ b/block/accounting.c
@@ -94,6 +94,100 @@ void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
cookie->type = type;
}
+/* block_latency_histogram_compare_func
+ * Compare @key with interval [@el, @el+1), where @el+1 is a next array element
+ * after @el.
+ * Return: -1 if @key < @el
+ * 0 if @key in [@el, @el+1)
+ * +1 if @key >= @el+1
+ */
+static int block_latency_histogram_compare_func(const void *key, const void *el)
+{
+ uint64_t k = *(uint64_t *)key;
+ uint64_t a = *(uint64_t *)el;
+ uint64_t b = *((uint64_t *)el + 1);
+
+ return k < a ? -1 : (k < b ? 0 : 1);
+}
+
+static void block_latency_histogram_account(BlockLatencyHistogram *hist,
+ enum BlockAcctType type,
+ int64_t latency_ns)
+{
+ uint64_t *data, *pos;
+
+ if (hist->points == NULL) {
+ /* histogram disabled */
+ return;
+ }
+
+ data = hist->histogram[type];
+
+ if (latency_ns < hist->points[0]) {
+ data[0]++;
+ return;
+ }
+
+ if (latency_ns >= hist->points[hist->size - 2]) {
+ data[hist->size - 1]++;
+ return;
+ }
+
+ pos = bsearch(&latency_ns, hist->points, hist->size - 2,
+ sizeof(hist->points[0]),
+ block_latency_histogram_compare_func);
+ assert(pos != NULL);
+
+ data[pos - hist->points + 1]++;
+}
+
+int block_latency_histogram_set(BlockAcctStats *stats, uint64List *latency)
+{
+ BlockLatencyHistogram *hist = &stats->latency_histogram;
+ uint64List *entry;
+ uint64_t *ptr;
+ int i;
+ uint64_t prev = 0;
+
+ hist->size = 1;
+
+ for (entry = latency; entry; entry = entry->next) {
+ if (entry->value <= prev) {
+ return -EINVAL;
+ }
+ hist->size++;
+ prev = entry->value;
+ }
+
+ hist->points = g_renew(uint64_t, hist->points, hist->size - 1);
+ for (entry = latency, ptr = hist->points; entry;
+ entry = entry->next, ptr++)
+ {
+ *ptr = entry->value;
+ }
+
+ for (i = 0; i < BLOCK_MAX_IOTYPE; i++) {
+ hist->histogram[i] = g_renew(uint64_t, hist->histogram[i], hist->size);
+ memset(hist->histogram[i], 0, hist->size * sizeof(uint64_t));
+ }
+
+ return 0;
+}
+
+void block_latency_histogram_clear(BlockAcctStats *stats)
+{
+ BlockLatencyHistogram *hist = &stats->latency_histogram;
+ int i;
+
+ g_free(hist->points);
+ hist->points = NULL;
+
+ for (i = 0; i < BLOCK_MAX_IOTYPE; i++) {
+ g_free(hist->histogram[i]);
+ hist->histogram[i] = NULL;
+ }
+}
+
static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
bool failed)
{
@@ -116,6 +210,9 @@ static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
stats->nr_ops[cookie->type]++;
}
+ block_latency_histogram_account(&stats->latency_histogram, cookie->type,
+ latency_ns);
+
if (!failed || stats->account_failed) {
stats->total_time_ns[cookie->type] += latency_ns;
stats->last_access_time_ns = time_ns;
--
2.11.1
next prev parent reply other threads:[~2018-02-07 12:50 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-07 12:50 [Qemu-devel] [PATCH v2 0/2] block latency histogram Vladimir Sementsov-Ogievskiy
2018-02-07 12:50 ` Vladimir Sementsov-Ogievskiy [this message]
2018-03-05 14:36 ` [Qemu-devel] [PATCH v2 1/2] block/accounting: introduce " Vladimir Sementsov-Ogievskiy
2018-03-06 15:32 ` Stefan Hajnoczi
2018-03-08 17:31 ` Eric Blake
2018-03-08 18:14 ` Vladimir Sementsov-Ogievskiy
2018-03-08 18:21 ` Vladimir Sementsov-Ogievskiy
2018-03-08 18:58 ` Vladimir Sementsov-Ogievskiy
2018-03-08 19:49 ` Eric Blake
2018-02-07 12:50 ` [Qemu-devel] [PATCH v2 2/2] qapi: add block latency histogram interface Vladimir Sementsov-Ogievskiy
2018-03-06 15:58 ` Stefan Hajnoczi
2018-02-07 13:20 ` [Qemu-devel] [PATCH v2 0/2] block latency histogram no-reply
2018-02-07 13:29 ` Vladimir Sementsov-Ogievskiy
2018-02-15 9:38 ` [Qemu-devel] ping " Vladimir Sementsov-Ogievskiy
2018-03-02 10:27 ` Vladimir Sementsov-Ogievskiy
2018-03-06 16:00 ` [Qemu-devel] " Stefan Hajnoczi
2018-03-06 17:49 ` Emilio G. Cota
2018-03-08 11:42 ` Vladimir Sementsov-Ogievskiy
2018-03-08 18:56 ` Emilio G. Cota
2018-03-08 19:07 ` Vladimir Sementsov-Ogievskiy
2018-03-08 20:05 ` Emilio G. Cota
2018-03-08 17:32 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180207125037.13510-2-vsementsov@virtuozzo.com \
--to=vsementsov@virtuozzo.com \
--cc=armbru@redhat.com \
--cc=den@openvz.org \
--cc=eblake@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=nshirokovskiy@virtuozzo.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).