[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/6] qcow2: use one single memory block for the L2/r
From: |
Alberto Garcia |
Subject: |
[Qemu-devel] [PATCH 1/6] qcow2: use one single memory block for the L2/refcount cache tables |
Date: |
Thu, 30 Apr 2015 13:11:40 +0300 |
The qcow2 L2/refcount cache contains one separate table for each cache
entry. Doing one allocation per table adds unnecessary overhead and it
also requires us to store the address of each table separately.
Since the size of the cache is constant during its lifetime, it's
better to have an array that contains all the tables using one single
allocation.
In my tests measuring freshly created caches with sizes 128MB (L2) and
32MB (refcount) this uses around 10MB of RAM less.
Signed-off-by: Alberto Garcia <address@hidden>
---
block/qcow2-cache.c | 48 +++++++++++++++++++++---------------------------
1 file changed, 21 insertions(+), 27 deletions(-)
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index b115549..586880b 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -28,7 +28,6 @@
#include "trace.h"
typedef struct Qcow2CachedTable {
- void* table;
int64_t offset;
bool dirty;
int cache_hits;
@@ -40,39 +39,34 @@ struct Qcow2Cache {
struct Qcow2Cache* depends;
int size;
bool depends_on_flush;
+ void *table_array;
+ int table_size;
};
+static inline void *table_addr(Qcow2Cache *c, int table)
+{
+ return c->table_array + table * c->table_size;
+}
+
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables)
{
BDRVQcowState *s = bs->opaque;
Qcow2Cache *c;
- int i;
c = g_new0(Qcow2Cache, 1);
c->size = num_tables;
+ c->table_size = s->cluster_size;
c->entries = g_try_new0(Qcow2CachedTable, num_tables);
- if (!c->entries) {
- goto fail;
- }
+ c->table_array = qemu_try_blockalign(bs->file, num_tables * c->table_size);
- for (i = 0; i < c->size; i++) {
- c->entries[i].table = qemu_try_blockalign(bs->file, s->cluster_size);
- if (c->entries[i].table == NULL) {
- goto fail;
- }
+ if (!c->entries || !c->table_array) {
+ qemu_vfree(c->table_array);
+ g_free(c->entries);
+ g_free(c);
+ c = NULL;
}
return c;
-
-fail:
- if (c->entries) {
- for (i = 0; i < c->size; i++) {
- qemu_vfree(c->entries[i].table);
- }
- }
- g_free(c->entries);
- g_free(c);
- return NULL;
}
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c)
@@ -81,9 +75,9 @@ int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c)
for (i = 0; i < c->size; i++) {
assert(c->entries[i].ref == 0);
- qemu_vfree(c->entries[i].table);
}
+ qemu_vfree(c->table_array);
g_free(c->entries);
g_free(c);
@@ -151,8 +145,8 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs,
Qcow2Cache *c, int i)
BLKDBG_EVENT(bs->file, BLKDBG_L2_UPDATE);
}
- ret = bdrv_pwrite(bs->file, c->entries[i].offset, c->entries[i].table,
- s->cluster_size);
+ ret = bdrv_pwrite(bs->file, c->entries[i].offset, table_addr(c, i),
+ s->cluster_size);
if (ret < 0) {
return ret;
}
@@ -304,7 +298,7 @@ static int qcow2_cache_do_get(BlockDriverState *bs,
Qcow2Cache *c,
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
}
- ret = bdrv_pread(bs->file, offset, c->entries[i].table,
s->cluster_size);
+ ret = bdrv_pread(bs->file, offset, table_addr(c, i), s->cluster_size);
if (ret < 0) {
return ret;
}
@@ -319,7 +313,7 @@ static int qcow2_cache_do_get(BlockDriverState *bs,
Qcow2Cache *c,
found:
c->entries[i].cache_hits++;
c->entries[i].ref++;
- *table = c->entries[i].table;
+ *table = table_addr(c, i);
trace_qcow2_cache_get_done(qemu_coroutine_self(),
c == s->l2_table_cache, i);
@@ -344,7 +338,7 @@ int qcow2_cache_put(BlockDriverState *bs, Qcow2Cache *c,
void **table)
int i;
for (i = 0; i < c->size; i++) {
- if (c->entries[i].table == *table) {
+ if (table_addr(c, i) == *table) {
goto found;
}
}
@@ -363,7 +357,7 @@ void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void
*table)
int i;
for (i = 0; i < c->size; i++) {
- if (c->entries[i].table == table) {
+ if (table_addr(c, i) == table) {
goto found;
}
}
--
2.1.4
- [Qemu-devel] [PATCH 0/6] qcow2 L2/refcount cache improvements, Alberto Garcia, 2015/04/30
- [Qemu-devel] [PATCH 6/6] qcow2: style fixes in qcow2-cache.c, Alberto Garcia, 2015/04/30
- [Qemu-devel] [PATCH 5/6] qcow2: use a hash to look for entries in the L2 cache, Alberto Garcia, 2015/04/30
- [Qemu-devel] [PATCH 2/6] qcow2: simplify qcow2_cache_put() and qcow2_cache_entry_mark_dirty(), Alberto Garcia, 2015/04/30
- [Qemu-devel] [PATCH 4/6] qcow2: remove qcow2_cache_find_entry_to_replace(), Alberto Garcia, 2015/04/30
- [Qemu-devel] [PATCH 1/6] qcow2: use one single memory block for the L2/refcount cache tables,
Alberto Garcia <=
- [Qemu-devel] [PATCH 3/6] qcow2: use an LRU algorithm to replace entries from the L2 cache, Alberto Garcia, 2015/04/30