[Top][All Lists]

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

[Qemu-block] [PATCH] qcow2: Optimize L2 table cache size based on image

From: Ed Swierk
Subject: [Qemu-block] [PATCH] qcow2: Optimize L2 table cache size based on image and cluster sizes
Date: Tue, 4 Oct 2016 06:39:52 -0700

The optimal size of the qcow2 L2 table cache depends on the working
set size and the cluster size of the disk image. If the cache is too
small, L2 tables are be 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 table 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 L2 table cache size can be set manually via the l2-cache-size
runtime option, but such a performance-critical value needs a sane
default. Conservatively assuming the entire image is the working
set, the existing hardcoded default value of 1 MiB is appropriate
for images up to 8 GiB with the default 64 KiB cluster size.

This change replaces the hardcoded default L2 table cache size with a
value computed from the image size and cluster size. The resulting
default cache size is just large enough to service random accesses in
the entire image.

Signed-off-by: Ed Swierk <address@hidden>
 block/qcow2.c | 5 ++---
 block/qcow2.h | 4 ----
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/block/qcow2.c b/block/qcow2.c
index 91ef4df..259e377 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -563,9 +563,8 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts 
     } else {
         if (!l2_cache_size_set && !refcount_cache_size_set) {
-            *l2_cache_size = MAX(DEFAULT_L2_CACHE_BYTE_SIZE,
-                                 (uint64_t)DEFAULT_L2_CACHE_CLUSTERS
-                                 * s->cluster_size);
+            *l2_cache_size = (bs->total_sectors * BDRV_SECTOR_SIZE * 8
+                              + s->cluster_size - 1) / s->cluster_size;
             *refcount_cache_size = *l2_cache_size
                                  / DEFAULT_L2_REFCOUNT_SIZE_RATIO;
         } else if (!l2_cache_size_set) {
diff --git a/block/qcow2.h b/block/qcow2.h
index b36a7bf..f148c4d 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -68,10 +68,6 @@
 /* Must be at least 4 to cover all cases of refcount table growth */
 #define MIN_REFCOUNT_CACHE_SIZE 4 /* clusters */
-/* Whichever is more */
-#define DEFAULT_L2_CACHE_CLUSTERS 8 /* clusters */
-#define DEFAULT_L2_CACHE_BYTE_SIZE 1048576 /* bytes */
 /* The refblock cache needs only a fourth of the L2 cache size to cover as many
  * clusters */

reply via email to

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