qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench
@ 2016-06-03 12:30 Kevin Wolf
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 1/5] " Kevin Wolf
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 12:30 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, eblake, den, qemu-devel

After merging Den's qcow2 patch to avoid duplicated flushes, I thought I would
be nice to reproduce the problem and I remembered 'qemu-img bench', which I had
posted before as part of more than one RFC series, but which never made it to
master somehow. So here is a rebased and cleaned up version of it, just by
itself, so that it hopefully can be merged finally.

Of course, I failed to actually reproduce the problem on my laptop. Who knows,
something on my system might be more intelligent about useless flushes, or
maybe I just misunderstood what the problematic scenario looks like at the
block level. Doesn't make the tool less useful, though, and I already did the
rebasing.

Kevin Wolf (5):
  qemu-img bench
  qemu-img bench: Sequential writes
  qemu-img bench: Make start offset configurable
  qemu-img bench: Implement -S (step size)
  qemu-img bench: Add --flush-interval

 qemu-img-cmds.hx |   6 ++
 qemu-img.c       | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-img.texi    |  19 ++++
 3 files changed, 314 insertions(+)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 1/5] qemu-img bench
  2016-06-03 12:30 [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench Kevin Wolf
@ 2016-06-03 12:30 ` Kevin Wolf
  2016-06-06  9:59   ` Denis V. Lunev
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 2/5] qemu-img bench: Sequential writes Kevin Wolf
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 12:30 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, eblake, den, qemu-devel

This adds a qemu-img command that allows doing some simple benchmarks
for the block layer without involving guest devices and a real VM.

For the start, this implements only a test of sequential reads.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img-cmds.hx |   6 ++
 qemu-img.c       | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-img.texi    |  10 +++
 3 files changed, 206 insertions(+)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index e7cded6..f3bd546 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -9,6 +9,12 @@ STEXI
 @table @option
 ETEXI
 
+DEF("bench", img_bench,
+    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] filename")
+STEXI
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
+ETEXI
+
 DEF("check", img_check,
     "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
 STEXI
diff --git a/qemu-img.c b/qemu-img.c
index 4b56ad3..d471d10 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3459,6 +3459,196 @@ out_no_progress:
     return 0;
 }
 
+typedef struct BenchData {
+    BlockBackend *blk;
+    uint64_t image_size;
+    int bufsize;
+    int nrreq;
+    int n;
+    uint8_t *buf;
+    QEMUIOVector *qiov;
+
+    int in_flight;
+    uint64_t offset;
+} BenchData;
+
+static void bench_cb(void *opaque, int ret)
+{
+    BenchData *b = opaque;
+    BlockAIOCB *acb;
+
+    if (ret < 0) {
+        error_report("Failed request: %s\n", strerror(-ret));
+        exit(EXIT_FAILURE);
+    }
+    if (b->in_flight > 0) {
+        b->n--;
+        b->in_flight--;
+    }
+
+    while (b->n > b->in_flight && b->in_flight < b->nrreq) {
+        acb = blk_aio_preadv(b->blk, b->offset, b->qiov, 0,
+                             bench_cb, b);
+        if (!acb) {
+            error_report("Failed to issue request");
+            exit(EXIT_FAILURE);
+        }
+        b->in_flight++;
+        b->offset += b->bufsize;
+        b->offset %= b->image_size;
+    }
+}
+
+static int img_bench(int argc, char **argv)
+{
+    int c, ret = 0;
+    const char *fmt = NULL, *filename;
+    bool quiet = false;
+    bool image_opts = false;
+    int count = 75000;
+    int depth = 64;
+    size_t bufsize = 4096;
+    int64_t image_size;
+    BlockBackend *blk = NULL;
+    BenchData data = {};
+    int flags = 0;
+    bool writethrough;
+    struct timeval t1, t2;
+    int i;
+
+    for (;;) {
+        static const struct option long_options[] = {
+            {"help", no_argument, 0, 'h'},
+            {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+            {0, 0, 0, 0}
+        };
+        c = getopt_long(argc, argv, "hc:d:f:nqs:t:", long_options, NULL);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+        case 'h':
+        case '?':
+            help();
+            break;
+        case 'c':
+        {
+            char *end;
+            errno = 0;
+            count = strtoul(optarg, &end, 0);
+            if (errno || *end || count > INT_MAX) {
+                error_report("Invalid request count specified");
+                return 1;
+            }
+            break;
+        }
+        case 'd':
+        {
+            char *end;
+            errno = 0;
+            depth = strtoul(optarg, &end, 0);
+            if (errno || *end || depth > INT_MAX) {
+                error_report("Invalid queue depth specified");
+                return 1;
+            }
+            break;
+        }
+        case 'f':
+            fmt = optarg;
+            break;
+        case 'n':
+            flags |= BDRV_O_NATIVE_AIO;
+            break;
+        case 'q':
+            quiet = true;
+            break;
+        case 's':
+        {
+            int64_t sval;
+            char *end;
+
+            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+            if (sval < 0 || sval > INT_MAX || *end) {
+                error_report("Invalid buffer size specified");
+                return 1;
+            }
+
+            bufsize = sval;
+            break;
+        }
+        case 't':
+            ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
+            if (ret < 0) {
+                error_report("Invalid cache mode");
+                ret = -1;
+                goto out;
+            }
+            break;
+        case OPTION_IMAGE_OPTS:
+            image_opts = true;
+            break;
+        }
+    }
+
+    if (optind != argc - 1) {
+        error_exit("Expecting one image file name");
+    }
+    filename = argv[argc - 1];
+
+    blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
+    if (!blk) {
+        ret = -1;
+        goto out;
+    }
+
+    image_size = blk_getlength(blk);
+    if (image_size < 0) {
+        ret = image_size;
+        goto out;
+    }
+
+    data = (BenchData) {
+        .blk        = blk,
+        .image_size = image_size,
+        .bufsize    = bufsize,
+        .nrreq      = depth,
+        .n          = count,
+    };
+    printf("Sending %d requests, %d bytes each, %d in parallel\n",
+        data.n, data.bufsize, data.nrreq);
+
+    data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
+    data.qiov = g_new(QEMUIOVector, data.nrreq);
+    for (i = 0; i < data.nrreq; i++) {
+        qemu_iovec_init(&data.qiov[i], 1);
+        qemu_iovec_add(&data.qiov[i],
+                       data.buf + i * data.bufsize, data.bufsize);
+    }
+
+    gettimeofday(&t1, NULL);
+    bench_cb(&data, 0);
+
+    while (data.n > 0) {
+        main_loop_wait(false);
+    }
+    gettimeofday(&t2, NULL);
+
+    printf("Run completed in %3.3f seconds.\n",
+           (t2.tv_sec - t1.tv_sec)
+           + ((double)(t2.tv_usec - t1.tv_usec) / 1000000));
+
+out:
+    qemu_vfree(data.buf);
+    blk_unref(blk);
+
+    if (ret) {
+        return 1;
+    }
+    return 0;
+}
+
+
 static const img_cmd_t img_cmds[] = {
 #define DEF(option, callback, arg_string)        \
     { option, callback },
diff --git a/qemu-img.texi b/qemu-img.texi
index afaebdd..b6b28e3 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -131,6 +131,16 @@ Skip the creation of the target volume
 Command description:
 
 @table @option
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
+
+Run a simple sequential read benchmark on the specified image. A total number
+of @var{count} I/O requests is performed, each @var{buffer_size} bytes in size,
+and with @var{depth} requests in parallel.
+
+If @code{-n} is specified, the native AIO backend is used if possible. On
+Linux, this option only works if @code{-t none} or @code{-t directsync} is
+specified as well.
+
 @item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
 
 Perform a consistency check on the disk image @var{filename}. The command can
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 2/5] qemu-img bench: Sequential writes
  2016-06-03 12:30 [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench Kevin Wolf
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 1/5] " Kevin Wolf
@ 2016-06-03 12:30 ` Kevin Wolf
  2016-06-03 14:55   ` Denis V. Lunev
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 3/5] qemu-img bench: Make start offset configurable Kevin Wolf
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 12:30 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, eblake, den, qemu-devel

This extends qemu-img bench with an option that makes it use sequential
writes instead of reads for the test run.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img-cmds.hx |  4 ++--
 qemu-img.c       | 24 +++++++++++++++++++-----
 qemu-img.texi    | 10 ++++++----
 3 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index f3bd546..d651674 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -10,9 +10,9 @@ STEXI
 ETEXI
 
 DEF("bench", img_bench,
-    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] filename")
+    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] [-w] filename")
 STEXI
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
 ETEXI
 
 DEF("check", img_check,
diff --git a/qemu-img.c b/qemu-img.c
index d471d10..142efb1 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3462,6 +3462,7 @@ out_no_progress:
 typedef struct BenchData {
     BlockBackend *blk;
     uint64_t image_size;
+    bool write;
     int bufsize;
     int nrreq;
     int n;
@@ -3487,8 +3488,13 @@ static void bench_cb(void *opaque, int ret)
     }
 
     while (b->n > b->in_flight && b->in_flight < b->nrreq) {
-        acb = blk_aio_preadv(b->blk, b->offset, b->qiov, 0,
-                             bench_cb, b);
+        if (b->write) {
+            acb = blk_aio_pwritev(b->blk, b->offset, b->qiov, 0,
+                                  bench_cb, b);
+        } else {
+            acb = blk_aio_preadv(b->blk, b->offset, b->qiov, 0,
+                                 bench_cb, b);
+        }
         if (!acb) {
             error_report("Failed to issue request");
             exit(EXIT_FAILURE);
@@ -3505,6 +3511,7 @@ static int img_bench(int argc, char **argv)
     const char *fmt = NULL, *filename;
     bool quiet = false;
     bool image_opts = false;
+    bool is_write = false;
     int count = 75000;
     int depth = 64;
     size_t bufsize = 4096;
@@ -3522,7 +3529,7 @@ static int img_bench(int argc, char **argv)
             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
             {0, 0, 0, 0}
         };
-        c = getopt_long(argc, argv, "hc:d:f:nqs:t:", long_options, NULL);
+        c = getopt_long(argc, argv, "hc:d:f:nqs:t:w", long_options, NULL);
         if (c == -1) {
             break;
         }
@@ -3585,6 +3592,10 @@ static int img_bench(int argc, char **argv)
                 goto out;
             }
             break;
+        case 'w':
+            flags |= BDRV_O_RDWR;
+            is_write = true;
+            break;
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -3614,11 +3625,14 @@ static int img_bench(int argc, char **argv)
         .bufsize    = bufsize,
         .nrreq      = depth,
         .n          = count,
+        .write      = is_write,
     };
-    printf("Sending %d requests, %d bytes each, %d in parallel\n",
-        data.n, data.bufsize, data.nrreq);
+    printf("Sending %d %s requests, %d bytes each, %d in parallel\n",
+           data.n, data.write ? "write" : "read", data.bufsize, data.nrreq);
 
     data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
+    memset(data.buf, 0, data.nrreq * data.bufsize);
+
     data.qiov = g_new(QEMUIOVector, data.nrreq);
     for (i = 0; i < data.nrreq; i++) {
         qemu_iovec_init(&data.qiov[i], 1);
diff --git a/qemu-img.texi b/qemu-img.texi
index b6b28e3..34e94db 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -131,11 +131,13 @@ Skip the creation of the target volume
 Command description:
 
 @table @option
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
 
-Run a simple sequential read benchmark on the specified image. A total number
-of @var{count} I/O requests is performed, each @var{buffer_size} bytes in size,
-and with @var{depth} requests in parallel.
+Run a simple sequential I/O benchmark on the specified image. If @code{-w} is
+specified, a write test is performed, otherwise a read test is performed.
+
+A total number of @var{count} I/O requests is performed, each @var{buffer_size}
+bytes in size, and with @var{depth} requests in parallel.
 
 If @code{-n} is specified, the native AIO backend is used if possible. On
 Linux, this option only works if @code{-t none} or @code{-t directsync} is
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 3/5] qemu-img bench: Make start offset configurable
  2016-06-03 12:30 [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench Kevin Wolf
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 1/5] " Kevin Wolf
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 2/5] qemu-img bench: Sequential writes Kevin Wolf
@ 2016-06-03 12:30 ` Kevin Wolf
  2016-06-06 10:02   ` Denis V. Lunev
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 4/5] qemu-img bench: Implement -S (step size) Kevin Wolf
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval Kevin Wolf
  4 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 12:30 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, eblake, den, qemu-devel

This patch adds an option the specify the offset of the first request
made by qemu-img bench. This allows to benchmark misaligned requests.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img-cmds.hx |  4 ++--
 qemu-img.c       | 23 ++++++++++++++++++++---
 qemu-img.texi    |  5 +++--
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index d651674..b9b521e 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -10,9 +10,9 @@ STEXI
 ETEXI
 
 DEF("bench", img_bench,
-    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] [-w] filename")
+    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-t cache] [-w] filename")
 STEXI
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
 ETEXI
 
 DEF("check", img_check,
diff --git a/qemu-img.c b/qemu-img.c
index 142efb1..fcac8b8 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3514,6 +3514,7 @@ static int img_bench(int argc, char **argv)
     bool is_write = false;
     int count = 75000;
     int depth = 64;
+    int64_t offset = 0;
     size_t bufsize = 4096;
     int64_t image_size;
     BlockBackend *blk = NULL;
@@ -3529,7 +3530,7 @@ static int img_bench(int argc, char **argv)
             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
             {0, 0, 0, 0}
         };
-        c = getopt_long(argc, argv, "hc:d:f:nqs:t:w", long_options, NULL);
+        c = getopt_long(argc, argv, "hc:d:f:no:qs:t:w", long_options, NULL);
         if (c == -1) {
             break;
         }
@@ -3567,6 +3568,19 @@ static int img_bench(int argc, char **argv)
         case 'n':
             flags |= BDRV_O_NATIVE_AIO;
             break;
+        case 'o':
+        {
+            char *end;
+            errno = 0;
+            offset = qemu_strtosz_suffix(optarg, &end,
+                                         QEMU_STRTOSZ_DEFSUFFIX_B);
+            if (offset < 0|| *end) {
+                error_report("Invalid offset specified");
+                return 1;
+            }
+            break;
+        }
+            break;
         case 'q':
             quiet = true;
             break;
@@ -3625,10 +3639,13 @@ static int img_bench(int argc, char **argv)
         .bufsize    = bufsize,
         .nrreq      = depth,
         .n          = count,
+        .offset     = offset,
         .write      = is_write,
     };
-    printf("Sending %d %s requests, %d bytes each, %d in parallel\n",
-           data.n, data.write ? "write" : "read", data.bufsize, data.nrreq);
+    printf("Sending %d %s requests, %d bytes each, %d in parallel "
+           "(starting at offset %" PRId64 ")\n",
+           data.n, data.write ? "write" : "read", data.bufsize, data.nrreq,
+           data.offset);
 
     data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
     memset(data.buf, 0, data.nrreq * data.bufsize);
diff --git a/qemu-img.texi b/qemu-img.texi
index 34e94db..c37380e 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -131,13 +131,14 @@ Skip the creation of the target volume
 Command description:
 
 @table @option
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
 
 Run a simple sequential I/O benchmark on the specified image. If @code{-w} is
 specified, a write test is performed, otherwise a read test is performed.
 
 A total number of @var{count} I/O requests is performed, each @var{buffer_size}
-bytes in size, and with @var{depth} requests in parallel.
+bytes in size, and with @var{depth} requests in parallel. The first request
+starts at the position given by @var{offset}.
 
 If @code{-n} is specified, the native AIO backend is used if possible. On
 Linux, this option only works if @code{-t none} or @code{-t directsync} is
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 4/5] qemu-img bench: Implement -S (step size)
  2016-06-03 12:30 [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench Kevin Wolf
                   ` (2 preceding siblings ...)
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 3/5] qemu-img bench: Make start offset configurable Kevin Wolf
@ 2016-06-03 12:30 ` Kevin Wolf
  2016-06-06 10:03   ` Denis V. Lunev
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval Kevin Wolf
  4 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 12:30 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, eblake, den, qemu-devel

With this new option, qemu-img bench can be told to advance the current
offset after each request by a different value than the buffer size.
This is useful for controlling the conditions for cluster allocation in
image formats (e.g. qcow2 cluster allocation with COW in front of the
request, or COW areas that aren't overwritten immediately).

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img-cmds.hx |  4 ++--
 qemu-img.c       | 25 +++++++++++++++++++++----
 qemu-img.texi    |  6 ++++--
 3 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index b9b521e..f5d0098 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -10,9 +10,9 @@ STEXI
 ETEXI
 
 DEF("bench", img_bench,
-    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-t cache] [-w] filename")
+    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-S step_size] [-t cache] [-w] filename")
 STEXI
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
 ETEXI
 
 DEF("check", img_check,
diff --git a/qemu-img.c b/qemu-img.c
index fcac8b8..ff99181 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3464,6 +3464,7 @@ typedef struct BenchData {
     uint64_t image_size;
     bool write;
     int bufsize;
+    int step;
     int nrreq;
     int n;
     uint8_t *buf;
@@ -3500,7 +3501,7 @@ static void bench_cb(void *opaque, int ret)
             exit(EXIT_FAILURE);
         }
         b->in_flight++;
-        b->offset += b->bufsize;
+        b->offset += b->step;
         b->offset %= b->image_size;
     }
 }
@@ -3516,6 +3517,7 @@ static int img_bench(int argc, char **argv)
     int depth = 64;
     int64_t offset = 0;
     size_t bufsize = 4096;
+    size_t step = 0;
     int64_t image_size;
     BlockBackend *blk = NULL;
     BenchData data = {};
@@ -3530,7 +3532,7 @@ static int img_bench(int argc, char **argv)
             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
             {0, 0, 0, 0}
         };
-        c = getopt_long(argc, argv, "hc:d:f:no:qs:t:w", long_options, NULL);
+        c = getopt_long(argc, argv, "hc:d:f:no:qs:S:t:w", long_options, NULL);
         if (c == -1) {
             break;
         }
@@ -3598,6 +3600,20 @@ static int img_bench(int argc, char **argv)
             bufsize = sval;
             break;
         }
+        case 'S':
+        {
+            int64_t sval;
+            char *end;
+
+            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
+            if (sval < 0 || sval > INT_MAX || *end) {
+                error_report("Invalid step size specified");
+                return 1;
+            }
+
+            step = sval;
+            break;
+        }
         case 't':
             ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
             if (ret < 0) {
@@ -3637,15 +3653,16 @@ static int img_bench(int argc, char **argv)
         .blk        = blk,
         .image_size = image_size,
         .bufsize    = bufsize,
+        .step       = step ?: bufsize,
         .nrreq      = depth,
         .n          = count,
         .offset     = offset,
         .write      = is_write,
     };
     printf("Sending %d %s requests, %d bytes each, %d in parallel "
-           "(starting at offset %" PRId64 ")\n",
+           "(starting at offset %" PRId64 ", step size %d)\n",
            data.n, data.write ? "write" : "read", data.bufsize, data.nrreq,
-           data.offset);
+           data.offset, data.step);
 
     data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
     memset(data.buf, 0, data.nrreq * data.bufsize);
diff --git a/qemu-img.texi b/qemu-img.texi
index c37380e..6b03d3f 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -131,14 +131,16 @@ Skip the creation of the target volume
 Command description:
 
 @table @option
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
 
 Run a simple sequential I/O benchmark on the specified image. If @code{-w} is
 specified, a write test is performed, otherwise a read test is performed.
 
 A total number of @var{count} I/O requests is performed, each @var{buffer_size}
 bytes in size, and with @var{depth} requests in parallel. The first request
-starts at the position given by @var{offset}.
+starts at the position given by @var{offset}, each following request increases
+the current position by @var{step_size}. If @var{step_size} is not given,
+@var{buffer_size} is used for its value.
 
 If @code{-n} is specified, the native AIO backend is used if possible. On
 Linux, this option only works if @code{-t none} or @code{-t directsync} is
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval
  2016-06-03 12:30 [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench Kevin Wolf
                   ` (3 preceding siblings ...)
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 4/5] qemu-img bench: Implement -S (step size) Kevin Wolf
@ 2016-06-03 12:30 ` Kevin Wolf
  2016-06-03 15:01   ` Denis V. Lunev
  4 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 12:30 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, eblake, den, qemu-devel

This options allows to flush the image periodically during write tests.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qemu-img-cmds.hx |  4 ++--
 qemu-img.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 qemu-img.texi    |  6 ++++-
 3 files changed, 67 insertions(+), 12 deletions(-)

diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index f5d0098..04d70d4 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -10,9 +10,9 @@ STEXI
 ETEXI
 
 DEF("bench", img_bench,
-    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-S step_size] [-t cache] [-w] filename")
+    "bench [-c count] [-d depth] [-f fmt] [--flush-interval=flush_interval] [-n] [-o offset] [-q] [-s buffer_size] [-S step_size] [-t cache] [-w] filename")
 STEXI
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [--flush-interval=@var{flush_interval}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
 ETEXI
 
 DEF("check", img_check,
diff --git a/qemu-img.c b/qemu-img.c
index ff99181..76904db 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -53,6 +53,7 @@ enum {
     OPTION_BACKING_CHAIN = 257,
     OPTION_OBJECT = 258,
     OPTION_IMAGE_OPTS = 259,
+    OPTION_FLUSH_INTERVAL = 260,
 };
 
 typedef enum OutputFormat {
@@ -3467,10 +3468,12 @@ typedef struct BenchData {
     int step;
     int nrreq;
     int n;
+    int flush_interval;
     uint8_t *buf;
     QEMUIOVector *qiov;
 
     int in_flight;
+    bool in_flush;
     uint64_t offset;
 } BenchData;
 
@@ -3483,9 +3486,29 @@ static void bench_cb(void *opaque, int ret)
         error_report("Failed request: %s\n", strerror(-ret));
         exit(EXIT_FAILURE);
     }
-    if (b->in_flight > 0) {
+
+    if (b->in_flush) {
+        /* Just finished a flush: Start next requests */
+        assert(b->in_flight == 0);
+        b->in_flush = false;
+    } else if (b->in_flight > 0) {
+        int remaining = b->n - b->in_flight;
+
         b->n--;
         b->in_flight--;
+
+        /* Time for flush? Drain queue, then flush */
+        if (b->flush_interval && remaining % b->flush_interval == 0) {
+            if (!b->in_flight) {
+                acb = blk_aio_flush(b->blk, bench_cb, b);
+                if (!acb) {
+                    error_report("Failed to issue flush request");
+                    exit(EXIT_FAILURE);
+                }
+                b->in_flush = true;
+            }
+            return;
+        }
     }
 
     while (b->n > b->in_flight && b->in_flight < b->nrreq) {
@@ -3518,6 +3541,7 @@ static int img_bench(int argc, char **argv)
     int64_t offset = 0;
     size_t bufsize = 4096;
     size_t step = 0;
+    int flush_interval = 0;
     int64_t image_size;
     BlockBackend *blk = NULL;
     BenchData data = {};
@@ -3529,6 +3553,7 @@ static int img_bench(int argc, char **argv)
     for (;;) {
         static const struct option long_options[] = {
             {"help", no_argument, 0, 'h'},
+            {"flush-interval", required_argument, 0, OPTION_FLUSH_INTERVAL},
             {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
             {0, 0, 0, 0}
         };
@@ -3626,6 +3651,17 @@ static int img_bench(int argc, char **argv)
             flags |= BDRV_O_RDWR;
             is_write = true;
             break;
+        case OPTION_FLUSH_INTERVAL:
+        {
+            char *end;
+            errno = 0;
+            flush_interval = strtoul(optarg, &end, 0);
+            if (errno || *end || flush_interval > INT_MAX) {
+                error_report("Invalid flush interval specified");
+                return 1;
+            }
+            break;
+        }
         case OPTION_IMAGE_OPTS:
             image_opts = true;
             break;
@@ -3637,6 +3673,17 @@ static int img_bench(int argc, char **argv)
     }
     filename = argv[argc - 1];
 
+    if (!is_write && flush_interval) {
+        error_report("--flush-interval is only available in write tests");
+        ret = -1;
+        goto out;
+    }
+    if (flush_interval && flush_interval < depth) {
+        error_report("Flush interval can't be smaller than depth");
+        ret = -1;
+        goto out;
+    }
+
     blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
     if (!blk) {
         ret = -1;
@@ -3650,19 +3697,23 @@ static int img_bench(int argc, char **argv)
     }
 
     data = (BenchData) {
-        .blk        = blk,
-        .image_size = image_size,
-        .bufsize    = bufsize,
-        .step       = step ?: bufsize,
-        .nrreq      = depth,
-        .n          = count,
-        .offset     = offset,
-        .write      = is_write,
+        .blk            = blk,
+        .image_size     = image_size,
+        .bufsize        = bufsize,
+        .step           = step ?: bufsize,
+        .nrreq          = depth,
+        .n              = count,
+        .offset         = offset,
+        .write          = is_write,
+        .flush_interval = flush_interval,
     };
     printf("Sending %d %s requests, %d bytes each, %d in parallel "
            "(starting at offset %" PRId64 ", step size %d)\n",
            data.n, data.write ? "write" : "read", data.bufsize, data.nrreq,
            data.offset, data.step);
+    if (flush_interval) {
+        printf("Sending flush every %d requests\n", flush_interval);
+    }
 
     data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
     memset(data.buf, 0, data.nrreq * data.bufsize);
diff --git a/qemu-img.texi b/qemu-img.texi
index 6b03d3f..270fb4c 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -131,7 +131,7 @@ Skip the creation of the target volume
 Command description:
 
 @table @option
-@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
+@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [--flush-interval=@var{flush_interval}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
 
 Run a simple sequential I/O benchmark on the specified image. If @code{-w} is
 specified, a write test is performed, otherwise a read test is performed.
@@ -142,6 +142,10 @@ starts at the position given by @var{offset}, each following request increases
 the current position by @var{step_size}. If @var{step_size} is not given,
 @var{buffer_size} is used for its value.
 
+If @var{flush_interval} is specified for a write test, the queue is drained and
+a flush is issued before new writes are made whenever the number of remaining
+requests is a multiple of @var{flush_interval}.
+
 If @code{-n} is specified, the native AIO backend is used if possible. On
 Linux, this option only works if @code{-t none} or @code{-t directsync} is
 specified as well.
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 2/5] qemu-img bench: Sequential writes
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 2/5] qemu-img bench: Sequential writes Kevin Wolf
@ 2016-06-03 14:55   ` Denis V. Lunev
  0 siblings, 0 replies; 13+ messages in thread
From: Denis V. Lunev @ 2016-06-03 14:55 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: mreitz, eblake, qemu-devel

On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> This extends qemu-img bench with an option that makes it use sequential
> writes instead of reads for the test run.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>   qemu-img-cmds.hx |  4 ++--
>   qemu-img.c       | 24 +++++++++++++++++++-----
>   qemu-img.texi    | 10 ++++++----
>   3 files changed, 27 insertions(+), 11 deletions(-)
>
> diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
> index f3bd546..d651674 100644
> --- a/qemu-img-cmds.hx
> +++ b/qemu-img-cmds.hx
> @@ -10,9 +10,9 @@ STEXI
>   ETEXI
>   
>   DEF("bench", img_bench,
> -    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] filename")
> +    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] [-w] filename")
>   STEXI
> -@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
>   ETEXI
>   
>   DEF("check", img_check,
> diff --git a/qemu-img.c b/qemu-img.c
> index d471d10..142efb1 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -3462,6 +3462,7 @@ out_no_progress:
>   typedef struct BenchData {
>       BlockBackend *blk;
>       uint64_t image_size;
> +    bool write;
>       int bufsize;
>       int nrreq;
>       int n;
> @@ -3487,8 +3488,13 @@ static void bench_cb(void *opaque, int ret)
>       }
>   
>       while (b->n > b->in_flight && b->in_flight < b->nrreq) {
> -        acb = blk_aio_preadv(b->blk, b->offset, b->qiov, 0,
> -                             bench_cb, b);
> +        if (b->write) {
> +            acb = blk_aio_pwritev(b->blk, b->offset, b->qiov, 0,
> +                                  bench_cb, b);
> +        } else {
> +            acb = blk_aio_preadv(b->blk, b->offset, b->qiov, 0,
> +                                 bench_cb, b);
> +        }
>           if (!acb) {
>               error_report("Failed to issue request");
>               exit(EXIT_FAILURE);
> @@ -3505,6 +3511,7 @@ static int img_bench(int argc, char **argv)
>       const char *fmt = NULL, *filename;
>       bool quiet = false;
>       bool image_opts = false;
> +    bool is_write = false;
>       int count = 75000;
>       int depth = 64;
>       size_t bufsize = 4096;
> @@ -3522,7 +3529,7 @@ static int img_bench(int argc, char **argv)
>               {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
>               {0, 0, 0, 0}
>           };
> -        c = getopt_long(argc, argv, "hc:d:f:nqs:t:", long_options, NULL);
> +        c = getopt_long(argc, argv, "hc:d:f:nqs:t:w", long_options, NULL);
>           if (c == -1) {
>               break;
>           }
> @@ -3585,6 +3592,10 @@ static int img_bench(int argc, char **argv)
>                   goto out;
>               }
>               break;
> +        case 'w':
> +            flags |= BDRV_O_RDWR;
> +            is_write = true;
> +            break;
>           case OPTION_IMAGE_OPTS:
>               image_opts = true;
>               break;
> @@ -3614,11 +3625,14 @@ static int img_bench(int argc, char **argv)
>           .bufsize    = bufsize,
>           .nrreq      = depth,
>           .n          = count,
> +        .write      = is_write,
>       };
> -    printf("Sending %d requests, %d bytes each, %d in parallel\n",
> -        data.n, data.bufsize, data.nrreq);
> +    printf("Sending %d %s requests, %d bytes each, %d in parallel\n",
> +           data.n, data.write ? "write" : "read", data.bufsize, data.nrreq);
>   
>       data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
> +    memset(data.buf, 0, data.nrreq * data.bufsize);
> +
using 0 could be controversal. Can you add -P option like one
in qemu-io to fill the pattern?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval Kevin Wolf
@ 2016-06-03 15:01   ` Denis V. Lunev
  2016-06-03 15:16     ` Kevin Wolf
  0 siblings, 1 reply; 13+ messages in thread
From: Denis V. Lunev @ 2016-06-03 15:01 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: mreitz, eblake, qemu-devel

On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> This options allows to flush the image periodically during write tests.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This pattern could be a bit different - you wait requests to finish
and after that start flush. In this case there is no gain with my
patch ;)

You should treat flush as ordinary write request i.e. place
request immediately without waiting for writes to finish.
May be this could be specified as an operation mode.

Den

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval
  2016-06-03 15:01   ` Denis V. Lunev
@ 2016-06-03 15:16     ` Kevin Wolf
  2016-06-06 12:33       ` [Qemu-devel] [Qemu-block] " Kevin Wolf
  0 siblings, 1 reply; 13+ messages in thread
From: Kevin Wolf @ 2016-06-03 15:16 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-block, mreitz, eblake, qemu-devel

Am 03.06.2016 um 17:01 hat Denis V. Lunev geschrieben:
> On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> >This options allows to flush the image periodically during write tests.
> >
> >Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> This pattern could be a bit different - you wait requests to finish
> and after that start flush. In this case there is no gain with my
> patch ;)
> 
> You should treat flush as ordinary write request i.e. place
> request immediately without waiting for writes to finish.
> May be this could be specified as an operation mode.

Hm, okay, I can try that.

What OS is running on your guest? Because I seem to remember that Linux
drains the queue before sending a flush command. This is why I
implemented it this way here. Maybe it changed in Linux, though.

Kevin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] qemu-img bench
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 1/5] " Kevin Wolf
@ 2016-06-06  9:59   ` Denis V. Lunev
  0 siblings, 0 replies; 13+ messages in thread
From: Denis V. Lunev @ 2016-06-06  9:59 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: mreitz, eblake, qemu-devel

On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> This adds a qemu-img command that allows doing some simple benchmarks
> for the block layer without involving guest devices and a real VM.
>
> For the start, this implements only a test of sequential reads.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>   qemu-img-cmds.hx |   6 ++
>   qemu-img.c       | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   qemu-img.texi    |  10 +++
>   3 files changed, 206 insertions(+)
>
> diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
> index e7cded6..f3bd546 100644
> --- a/qemu-img-cmds.hx
> +++ b/qemu-img-cmds.hx
> @@ -9,6 +9,12 @@ STEXI
>   @table @option
>   ETEXI
>   
> +DEF("bench", img_bench,
> +    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] filename")
> +STEXI
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
> +ETEXI
> +
>   DEF("check", img_check,
>       "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
>   STEXI
> diff --git a/qemu-img.c b/qemu-img.c
> index 4b56ad3..d471d10 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -3459,6 +3459,196 @@ out_no_progress:
>       return 0;
>   }
>   
> +typedef struct BenchData {
> +    BlockBackend *blk;
> +    uint64_t image_size;
> +    int bufsize;
> +    int nrreq;
> +    int n;
> +    uint8_t *buf;
> +    QEMUIOVector *qiov;
> +
> +    int in_flight;
> +    uint64_t offset;
> +} BenchData;
> +
> +static void bench_cb(void *opaque, int ret)
> +{
> +    BenchData *b = opaque;
> +    BlockAIOCB *acb;
> +
> +    if (ret < 0) {
> +        error_report("Failed request: %s\n", strerror(-ret));
> +        exit(EXIT_FAILURE);
> +    }
> +    if (b->in_flight > 0) {
> +        b->n--;
> +        b->in_flight--;
> +    }
> +
> +    while (b->n > b->in_flight && b->in_flight < b->nrreq) {
> +        acb = blk_aio_preadv(b->blk, b->offset, b->qiov, 0,
> +                             bench_cb, b);
> +        if (!acb) {
> +            error_report("Failed to issue request");
> +            exit(EXIT_FAILURE);
> +        }
> +        b->in_flight++;
> +        b->offset += b->bufsize;
> +        b->offset %= b->image_size;
> +    }
> +}
> +
> +static int img_bench(int argc, char **argv)
> +{
> +    int c, ret = 0;
> +    const char *fmt = NULL, *filename;
> +    bool quiet = false;
> +    bool image_opts = false;
> +    int count = 75000;
> +    int depth = 64;
> +    size_t bufsize = 4096;
> +    int64_t image_size;
> +    BlockBackend *blk = NULL;
> +    BenchData data = {};
> +    int flags = 0;
> +    bool writethrough;
> +    struct timeval t1, t2;
> +    int i;
> +
> +    for (;;) {
> +        static const struct option long_options[] = {
> +            {"help", no_argument, 0, 'h'},
> +            {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
> +            {0, 0, 0, 0}
> +        };
> +        c = getopt_long(argc, argv, "hc:d:f:nqs:t:", long_options, NULL);
> +        if (c == -1) {
> +            break;
> +        }
> +
> +        switch (c) {
> +        case 'h':
> +        case '?':
> +            help();
> +            break;
> +        case 'c':
> +        {
> +            char *end;
> +            errno = 0;
> +            count = strtoul(optarg, &end, 0);
> +            if (errno || *end || count > INT_MAX) {
> +                error_report("Invalid request count specified");
> +                return 1;
> +            }
> +            break;
> +        }
> +        case 'd':
> +        {
> +            char *end;
> +            errno = 0;
> +            depth = strtoul(optarg, &end, 0);
> +            if (errno || *end || depth > INT_MAX) {
> +                error_report("Invalid queue depth specified");
> +                return 1;
> +            }
> +            break;
> +        }
> +        case 'f':
> +            fmt = optarg;
> +            break;
> +        case 'n':
> +            flags |= BDRV_O_NATIVE_AIO;
> +            break;
> +        case 'q':
> +            quiet = true;
> +            break;
> +        case 's':
> +        {
> +            int64_t sval;
> +            char *end;
> +
> +            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
> +            if (sval < 0 || sval > INT_MAX || *end) {
> +                error_report("Invalid buffer size specified");
> +                return 1;
> +            }
> +
> +            bufsize = sval;
> +            break;
> +        }
> +        case 't':
> +            ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
> +            if (ret < 0) {
> +                error_report("Invalid cache mode");
> +                ret = -1;
> +                goto out;
> +            }
> +            break;
> +        case OPTION_IMAGE_OPTS:
> +            image_opts = true;
> +            break;
> +        }
> +    }
> +
> +    if (optind != argc - 1) {
> +        error_exit("Expecting one image file name");
> +    }
> +    filename = argv[argc - 1];
> +
> +    blk = img_open(image_opts, filename, fmt, flags, writethrough, quiet);
> +    if (!blk) {
> +        ret = -1;
> +        goto out;
> +    }
> +
> +    image_size = blk_getlength(blk);
> +    if (image_size < 0) {
> +        ret = image_size;
> +        goto out;
> +    }
> +
> +    data = (BenchData) {
> +        .blk        = blk,
> +        .image_size = image_size,
> +        .bufsize    = bufsize,
> +        .nrreq      = depth,
> +        .n          = count,
> +    };
> +    printf("Sending %d requests, %d bytes each, %d in parallel\n",
> +        data.n, data.bufsize, data.nrreq);
> +
> +    data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
> +    data.qiov = g_new(QEMUIOVector, data.nrreq);
> +    for (i = 0; i < data.nrreq; i++) {
> +        qemu_iovec_init(&data.qiov[i], 1);
> +        qemu_iovec_add(&data.qiov[i],
> +                       data.buf + i * data.bufsize, data.bufsize);
> +    }
> +
> +    gettimeofday(&t1, NULL);
> +    bench_cb(&data, 0);
> +
> +    while (data.n > 0) {
> +        main_loop_wait(false);
> +    }
> +    gettimeofday(&t2, NULL);
> +
> +    printf("Run completed in %3.3f seconds.\n",
> +           (t2.tv_sec - t1.tv_sec)
> +           + ((double)(t2.tv_usec - t1.tv_usec) / 1000000));
> +
> +out:
> +    qemu_vfree(data.buf);
> +    blk_unref(blk);
> +
> +    if (ret) {
> +        return 1;
> +    }
> +    return 0;
> +}
> +
> +
>   static const img_cmd_t img_cmds[] = {
>   #define DEF(option, callback, arg_string)        \
>       { option, callback },
> diff --git a/qemu-img.texi b/qemu-img.texi
> index afaebdd..b6b28e3 100644
> --- a/qemu-img.texi
> +++ b/qemu-img.texi
> @@ -131,6 +131,16 @@ Skip the creation of the target volume
>   Command description:
>   
>   @table @option
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] @var{filename}
> +
> +Run a simple sequential read benchmark on the specified image. A total number
> +of @var{count} I/O requests is performed, each @var{buffer_size} bytes in size,
> +and with @var{depth} requests in parallel.
> +
> +If @code{-n} is specified, the native AIO backend is used if possible. On
> +Linux, this option only works if @code{-t none} or @code{-t directsync} is
> +specified as well.
> +
>   @item check [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
>   
>   Perform a consistency check on the disk image @var{filename}. The command can
Reviewed-by: Denis V. Lunev <den@openvz.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 3/5] qemu-img bench: Make start offset configurable
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 3/5] qemu-img bench: Make start offset configurable Kevin Wolf
@ 2016-06-06 10:02   ` Denis V. Lunev
  0 siblings, 0 replies; 13+ messages in thread
From: Denis V. Lunev @ 2016-06-06 10:02 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: mreitz, eblake, qemu-devel

On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> This patch adds an option the specify the offset of the first request
> made by qemu-img bench. This allows to benchmark misaligned requests.
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>   qemu-img-cmds.hx |  4 ++--
>   qemu-img.c       | 23 ++++++++++++++++++++---
>   qemu-img.texi    |  5 +++--
>   3 files changed, 25 insertions(+), 7 deletions(-)
>
> diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
> index d651674..b9b521e 100644
> --- a/qemu-img-cmds.hx
> +++ b/qemu-img-cmds.hx
> @@ -10,9 +10,9 @@ STEXI
>   ETEXI
>   
>   DEF("bench", img_bench,
> -    "bench [-c count] [-d depth] [-f fmt] [-n] [-q] [-s buffer_size] [-t cache] [-w] filename")
> +    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-t cache] [-w] filename")
>   STEXI
> -@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
>   ETEXI
>   
>   DEF("check", img_check,
> diff --git a/qemu-img.c b/qemu-img.c
> index 142efb1..fcac8b8 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -3514,6 +3514,7 @@ static int img_bench(int argc, char **argv)
>       bool is_write = false;
>       int count = 75000;
>       int depth = 64;
> +    int64_t offset = 0;
>       size_t bufsize = 4096;
>       int64_t image_size;
>       BlockBackend *blk = NULL;
> @@ -3529,7 +3530,7 @@ static int img_bench(int argc, char **argv)
>               {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
>               {0, 0, 0, 0}
>           };
> -        c = getopt_long(argc, argv, "hc:d:f:nqs:t:w", long_options, NULL);
> +        c = getopt_long(argc, argv, "hc:d:f:no:qs:t:w", long_options, NULL);
>           if (c == -1) {
>               break;
>           }
> @@ -3567,6 +3568,19 @@ static int img_bench(int argc, char **argv)
>           case 'n':
>               flags |= BDRV_O_NATIVE_AIO;
>               break;
> +        case 'o':
> +        {
> +            char *end;
> +            errno = 0;
> +            offset = qemu_strtosz_suffix(optarg, &end,
> +                                         QEMU_STRTOSZ_DEFSUFFIX_B);
> +            if (offset < 0|| *end) {
> +                error_report("Invalid offset specified");
> +                return 1;
> +            }
> +            break;
> +        }
> +            break;
>           case 'q':
>               quiet = true;
>               break;
> @@ -3625,10 +3639,13 @@ static int img_bench(int argc, char **argv)
>           .bufsize    = bufsize,
>           .nrreq      = depth,
>           .n          = count,
> +        .offset     = offset,
>           .write      = is_write,
>       };
> -    printf("Sending %d %s requests, %d bytes each, %d in parallel\n",
> -           data.n, data.write ? "write" : "read", data.bufsize, data.nrreq);
> +    printf("Sending %d %s requests, %d bytes each, %d in parallel "
> +           "(starting at offset %" PRId64 ")\n",
> +           data.n, data.write ? "write" : "read", data.bufsize, data.nrreq,
> +           data.offset);
>   
>       data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
>       memset(data.buf, 0, data.nrreq * data.bufsize);
> diff --git a/qemu-img.texi b/qemu-img.texi
> index 34e94db..c37380e 100644
> --- a/qemu-img.texi
> +++ b/qemu-img.texi
> @@ -131,13 +131,14 @@ Skip the creation of the target volume
>   Command description:
>   
>   @table @option
> -@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
>   
>   Run a simple sequential I/O benchmark on the specified image. If @code{-w} is
>   specified, a write test is performed, otherwise a read test is performed.
>   
>   A total number of @var{count} I/O requests is performed, each @var{buffer_size}
> -bytes in size, and with @var{depth} requests in parallel.
> +bytes in size, and with @var{depth} requests in parallel. The first request
> +starts at the position given by @var{offset}.
>   
>   If @code{-n} is specified, the native AIO backend is used if possible. On
>   Linux, this option only works if @code{-t none} or @code{-t directsync} is
Reviewed-by: Denis V. Lunev <den@openvz.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 4/5] qemu-img bench: Implement -S (step size)
  2016-06-03 12:30 ` [Qemu-devel] [PATCH 4/5] qemu-img bench: Implement -S (step size) Kevin Wolf
@ 2016-06-06 10:03   ` Denis V. Lunev
  0 siblings, 0 replies; 13+ messages in thread
From: Denis V. Lunev @ 2016-06-06 10:03 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: mreitz, eblake, qemu-devel

On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> With this new option, qemu-img bench can be told to advance the current
> offset after each request by a different value than the buffer size.
> This is useful for controlling the conditions for cluster allocation in
> image formats (e.g. qcow2 cluster allocation with COW in front of the
> request, or COW areas that aren't overwritten immediately).
>
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>   qemu-img-cmds.hx |  4 ++--
>   qemu-img.c       | 25 +++++++++++++++++++++----
>   qemu-img.texi    |  6 ++++--
>   3 files changed, 27 insertions(+), 8 deletions(-)
>
> diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
> index b9b521e..f5d0098 100644
> --- a/qemu-img-cmds.hx
> +++ b/qemu-img-cmds.hx
> @@ -10,9 +10,9 @@ STEXI
>   ETEXI
>   
>   DEF("bench", img_bench,
> -    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-t cache] [-w] filename")
> +    "bench [-c count] [-d depth] [-f fmt] [-n] [-o offset] [-q] [-s buffer_size] [-S step_size] [-t cache] [-w] filename")
>   STEXI
> -@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
>   ETEXI
>   
>   DEF("check", img_check,
> diff --git a/qemu-img.c b/qemu-img.c
> index fcac8b8..ff99181 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -3464,6 +3464,7 @@ typedef struct BenchData {
>       uint64_t image_size;
>       bool write;
>       int bufsize;
> +    int step;
>       int nrreq;
>       int n;
>       uint8_t *buf;
> @@ -3500,7 +3501,7 @@ static void bench_cb(void *opaque, int ret)
>               exit(EXIT_FAILURE);
>           }
>           b->in_flight++;
> -        b->offset += b->bufsize;
> +        b->offset += b->step;
>           b->offset %= b->image_size;
>       }
>   }
> @@ -3516,6 +3517,7 @@ static int img_bench(int argc, char **argv)
>       int depth = 64;
>       int64_t offset = 0;
>       size_t bufsize = 4096;
> +    size_t step = 0;
>       int64_t image_size;
>       BlockBackend *blk = NULL;
>       BenchData data = {};
> @@ -3530,7 +3532,7 @@ static int img_bench(int argc, char **argv)
>               {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
>               {0, 0, 0, 0}
>           };
> -        c = getopt_long(argc, argv, "hc:d:f:no:qs:t:w", long_options, NULL);
> +        c = getopt_long(argc, argv, "hc:d:f:no:qs:S:t:w", long_options, NULL);
>           if (c == -1) {
>               break;
>           }
> @@ -3598,6 +3600,20 @@ static int img_bench(int argc, char **argv)
>               bufsize = sval;
>               break;
>           }
> +        case 'S':
> +        {
> +            int64_t sval;
> +            char *end;
> +
> +            sval = qemu_strtosz_suffix(optarg, &end, QEMU_STRTOSZ_DEFSUFFIX_B);
> +            if (sval < 0 || sval > INT_MAX || *end) {
> +                error_report("Invalid step size specified");
> +                return 1;
> +            }
> +
> +            step = sval;
> +            break;
> +        }
>           case 't':
>               ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
>               if (ret < 0) {
> @@ -3637,15 +3653,16 @@ static int img_bench(int argc, char **argv)
>           .blk        = blk,
>           .image_size = image_size,
>           .bufsize    = bufsize,
> +        .step       = step ?: bufsize,
>           .nrreq      = depth,
>           .n          = count,
>           .offset     = offset,
>           .write      = is_write,
>       };
>       printf("Sending %d %s requests, %d bytes each, %d in parallel "
> -           "(starting at offset %" PRId64 ")\n",
> +           "(starting at offset %" PRId64 ", step size %d)\n",
>              data.n, data.write ? "write" : "read", data.bufsize, data.nrreq,
> -           data.offset);
> +           data.offset, data.step);
>   
>       data.buf = blk_blockalign(blk, data.nrreq * data.bufsize);
>       memset(data.buf, 0, data.nrreq * data.bufsize);
> diff --git a/qemu-img.texi b/qemu-img.texi
> index c37380e..6b03d3f 100644
> --- a/qemu-img.texi
> +++ b/qemu-img.texi
> @@ -131,14 +131,16 @@ Skip the creation of the target volume
>   Command description:
>   
>   @table @option
> -@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-t @var{cache}] [-w] @var{filename}
> +@item bench [-c @var{count}] [-d @var{depth}] [-f @var{fmt}] [-n] [-o @var{offset}] [-q] [-s @var{buffer_size}] [-S @var{step_size}] [-t @var{cache}] [-w] @var{filename}
>   
>   Run a simple sequential I/O benchmark on the specified image. If @code{-w} is
>   specified, a write test is performed, otherwise a read test is performed.
>   
>   A total number of @var{count} I/O requests is performed, each @var{buffer_size}
>   bytes in size, and with @var{depth} requests in parallel. The first request
> -starts at the position given by @var{offset}.
> +starts at the position given by @var{offset}, each following request increases
> +the current position by @var{step_size}. If @var{step_size} is not given,
> +@var{buffer_size} is used for its value.
>   
>   If @code{-n} is specified, the native AIO backend is used if possible. On
>   Linux, this option only works if @code{-t none} or @code{-t directsync} is
Reviewed-by: Denis V. Lunev <den@openvz.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 5/5] qemu-img bench: Add --flush-interval
  2016-06-03 15:16     ` Kevin Wolf
@ 2016-06-06 12:33       ` Kevin Wolf
  0 siblings, 0 replies; 13+ messages in thread
From: Kevin Wolf @ 2016-06-06 12:33 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: qemu-devel, qemu-block, mreitz

Am 03.06.2016 um 17:16 hat Kevin Wolf geschrieben:
> Am 03.06.2016 um 17:01 hat Denis V. Lunev geschrieben:
> > On 06/03/2016 03:30 PM, Kevin Wolf wrote:
> > >This options allows to flush the image periodically during write tests.
> > >
> > >Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > This pattern could be a bit different - you wait requests to finish
> > and after that start flush. In this case there is no gain with my
> > patch ;)
> > 
> > You should treat flush as ordinary write request i.e. place
> > request immediately without waiting for writes to finish.
> > May be this could be specified as an operation mode.
> 
> Hm, okay, I can try that.

Doesn't make a difference for me. But I'll include the option in v2
anyway.

Kevin

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-06-06 12:33 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-03 12:30 [Qemu-devel] [PATCH 0/5] block: Introduce qemu-img bench Kevin Wolf
2016-06-03 12:30 ` [Qemu-devel] [PATCH 1/5] " Kevin Wolf
2016-06-06  9:59   ` Denis V. Lunev
2016-06-03 12:30 ` [Qemu-devel] [PATCH 2/5] qemu-img bench: Sequential writes Kevin Wolf
2016-06-03 14:55   ` Denis V. Lunev
2016-06-03 12:30 ` [Qemu-devel] [PATCH 3/5] qemu-img bench: Make start offset configurable Kevin Wolf
2016-06-06 10:02   ` Denis V. Lunev
2016-06-03 12:30 ` [Qemu-devel] [PATCH 4/5] qemu-img bench: Implement -S (step size) Kevin Wolf
2016-06-06 10:03   ` Denis V. Lunev
2016-06-03 12:30 ` [Qemu-devel] [PATCH 5/5] qemu-img bench: Add --flush-interval Kevin Wolf
2016-06-03 15:01   ` Denis V. Lunev
2016-06-03 15:16     ` Kevin Wolf
2016-06-06 12:33       ` [Qemu-devel] [Qemu-block] " Kevin Wolf

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).