qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-block] [PATCH v2] qcow2: Add cache-size=max option to optimize cac


From: Ed Swierk
Subject: [Qemu-block] [PATCH v2] qcow2: Add cache-size=max option to optimize caches for performance
Date: Tue, 4 Oct 2016 11:19:44 -0700

The optimal size of the qcow2 L2 cache depends on the working set size
and the cluster size of the virtual disk. If the cache is too small,
L2 tables are re-read from disk on every IO operation in the worst
case. The host's buffer cache can paper over this inefficiency, but
with cache=none or cache=directsync, L2 cache thrashing dramatically
reduces IO operations per second (e.g. from 50k/sec to 5k/sec for a
qcow2 stored on a modern SSD).

The default L2 cache size of 1 MB is optimal for an 8 GB working set
in a virtual disk with a 64 KB cluster size. The user can control the
cache size manually via the l2-cache-size and cache-size options, but
still has to compute the correct size based on working set and cluster
sizes.

This change adds a cache-size=max option that tells qemu to optimize
for qcow2 performance, making the L2 and refcount caches as large as
necessary to cover the entire virtual disk.

Signed-off-by: Ed Swierk <address@hidden>
---
 block/qcow2.c        | 16 +++++++++++++---
 docs/qcow2-cache.txt | 10 ++++++++--
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 91ef4df..6f3a6ed 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -442,7 +442,7 @@ static QemuOptsList qcow2_runtime_opts = {
         },
         {
             .name = QCOW2_OPT_CACHE_SIZE,
-            .type = QEMU_OPT_SIZE,
+            .type = QEMU_OPT_STRING,
             .help = "Maximum combined metadata (L2 tables and refcount blocks) 
"
                     "cache size",
         },
@@ -525,18 +525,28 @@ static void read_cache_sizes(BlockDriverState *bs, 
QemuOpts *opts,
 {
     BDRVQcow2State *s = bs->opaque;
     uint64_t combined_cache_size;
-    bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
+    bool l2_cache_size_set, refcount_cache_size_set;
+    const char *combined_cache_size_set;
 
     combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
     l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
     refcount_cache_size_set = qemu_opt_get(opts, 
QCOW2_OPT_REFCOUNT_CACHE_SIZE);
 
-    combined_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_CACHE_SIZE, 0);
     *l2_cache_size = qemu_opt_get_size(opts, QCOW2_OPT_L2_CACHE_SIZE, 0);
     *refcount_cache_size = qemu_opt_get_size(opts,
                                              QCOW2_OPT_REFCOUNT_CACHE_SIZE, 0);
 
     if (combined_cache_size_set) {
+        if (strcasecmp(combined_cache_size_set, "max"))
+            parse_option_size(QCOW2_OPT_CACHE_SIZE, combined_cache_size_set,
+                              &combined_cache_size, &error_abort);
+        else
+            combined_cache_size =
+                (bs->total_sectors * BDRV_SECTOR_SIZE * 8
+                 + s->cluster_size - 1) / s->cluster_size
+                * (DEFAULT_L2_REFCOUNT_SIZE_RATIO + 1)
+                / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
+
         if (l2_cache_size_set && refcount_cache_size_set) {
             error_setg(errp, QCOW2_OPT_CACHE_SIZE ", " QCOW2_OPT_L2_CACHE_SIZE
                        " and " QCOW2_OPT_REFCOUNT_CACHE_SIZE " may not be set "
diff --git a/docs/qcow2-cache.txt b/docs/qcow2-cache.txt
index 5bb0607..c7ea9f3 100644
--- a/docs/qcow2-cache.txt
+++ b/docs/qcow2-cache.txt
@@ -114,9 +114,10 @@ There are three options available, and all of them take 
bytes:
 
 "l2-cache-size":         maximum size of the L2 table cache
 "refcount-cache-size":   maximum size of the refcount block cache
-"cache-size":            maximum size of both caches combined
+"cache-size":            maximum size of both caches combined, or
+                         "max" to cover entire disk
 
-There are two things that need to be taken into account:
+There are several things that need to be taken into account:
 
  - Both caches must have a size that is a multiple of the cluster
    size.
@@ -125,11 +126,16 @@ There are two things that need to be taken into account:
    adjust the others so that the L2 cache is 4 times bigger than the
    refcount cache.
 
+ - If you set cache-size to the special value "max", QEMU will
+   automatically size both caches to cover the entire virtual disk.
+
 This means that these options are equivalent:
 
    -drive file=hd.qcow2,l2-cache-size=2097152
    -drive file=hd.qcow2,refcount-cache-size=524288
    -drive file=hd.qcow2,cache-size=2621440
+   -drive file=hd.qcow2,cache-size=max [assuming hd.qcow2 is 16 GB
+                                        with 64 KB clusters]
 
 The reason for this 1/4 ratio is to ensure that both caches cover the
 same amount of disk space. Note however that this is only valid with
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]