aboutsummaryrefslogtreecommitdiff
path: root/migration
diff options
context:
space:
mode:
authorWei Wang <wei.w.wang@intel.com>2020-04-30 08:59:35 +0800
committerDr. David Alan Gilbert <dgilbert@redhat.com>2020-05-07 17:40:24 +0100
commite460a4b1a4c0e0aeea2c56bfc2407a9a1d1a3ae2 (patch)
treeded96ba444316c96f7c1c6caa4080fd774e67fb7 /migration
parent59c59c67ee6b0327ae932deb303caa47919aeb1e (diff)
migration/xbzrle: add encoding rate
Users may need to check the xbzrle encoding rate to know if the guest memory is xbzrle encoding-friendly, and dynamically turn off the encoding if the encoding rate is low. Signed-off-by: Yi Sun <yi.y.sun@intel.com> Signed-off-by: Wei Wang <wei.w.wang@intel.com> Message-Id: <1588208375-19556-1-git-send-email-wei.w.wang@intel.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Diffstat (limited to 'migration')
-rw-r--r--migration/migration.c1
-rw-r--r--migration/ram.c39
2 files changed, 38 insertions, 2 deletions
diff --git a/migration/migration.c b/migration/migration.c
index f5dbffc442..0bb042a0f7 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -932,6 +932,7 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
info->xbzrle_cache->pages = xbzrle_counters.pages;
info->xbzrle_cache->cache_miss = xbzrle_counters.cache_miss;
info->xbzrle_cache->cache_miss_rate = xbzrle_counters.cache_miss_rate;
+ info->xbzrle_cache->encoding_rate = xbzrle_counters.encoding_rate;
info->xbzrle_cache->overflow = xbzrle_counters.overflow;
}
diff --git a/migration/ram.c b/migration/ram.c
index 08eb382f53..859f835f1a 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -327,6 +327,10 @@ struct RAMState {
uint64_t num_dirty_pages_period;
/* xbzrle misses since the beginning of the period */
uint64_t xbzrle_cache_miss_prev;
+ /* Amount of xbzrle pages since the beginning of the period */
+ uint64_t xbzrle_pages_prev;
+ /* Amount of xbzrle encoded bytes since the beginning of the period */
+ uint64_t xbzrle_bytes_prev;
/* compression statistics since the beginning of the period */
/* amount of count that no free thread to compress data */
@@ -710,6 +714,18 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
return -1;
}
+ /*
+ * Reaching here means the page has hit the xbzrle cache, no matter what
+ * encoding result it is (normal encoding, overflow or skipping the page),
+ * count the page as encoded. This is used to caculate the encoding rate.
+ *
+ * Example: 2 pages (8KB) being encoded, first page encoding generates 2KB,
+ * 2nd page turns out to be skipped (i.e. no new bytes written to the
+ * page), the overall encoding rate will be 8KB / 2KB = 4, which has the
+ * skipped page included. In this way, the encoding rate can tell if the
+ * guest page is good for xbzrle encoding.
+ */
+ xbzrle_counters.pages++;
prev_cached_page = get_cached_data(XBZRLE.cache, current_addr);
/* save current buffer into memory */
@@ -740,6 +756,7 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
} else if (encoded_len == -1) {
trace_save_xbzrle_page_overflow();
xbzrle_counters.overflow++;
+ xbzrle_counters.bytes += TARGET_PAGE_SIZE;
return -1;
}
@@ -750,8 +767,12 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
qemu_put_be16(rs->f, encoded_len);
qemu_put_buffer(rs->f, XBZRLE.encoded_buf, encoded_len);
bytes_xbzrle += encoded_len + 1 + 2;
- xbzrle_counters.pages++;
- xbzrle_counters.bytes += bytes_xbzrle;
+ /*
+ * Like compressed_size (please see update_compress_thread_counts),
+ * the xbzrle encoded bytes don't count the 8 byte header with
+ * RAM_SAVE_FLAG_CONTINUE.
+ */
+ xbzrle_counters.bytes += bytes_xbzrle - 8;
ram_counters.transferred += bytes_xbzrle;
return 1;
@@ -884,9 +905,23 @@ static void migration_update_rates(RAMState *rs, int64_t end_time)
}
if (migrate_use_xbzrle()) {
+ double encoded_size, unencoded_size;
+
xbzrle_counters.cache_miss_rate = (double)(xbzrle_counters.cache_miss -
rs->xbzrle_cache_miss_prev) / page_count;
rs->xbzrle_cache_miss_prev = xbzrle_counters.cache_miss;
+ unencoded_size = (xbzrle_counters.pages - rs->xbzrle_pages_prev) *
+ TARGET_PAGE_SIZE;
+ encoded_size = xbzrle_counters.bytes - rs->xbzrle_bytes_prev;
+ if (xbzrle_counters.pages == rs->xbzrle_pages_prev) {
+ xbzrle_counters.encoding_rate = 0;
+ } else if (!encoded_size) {
+ xbzrle_counters.encoding_rate = UINT64_MAX;
+ } else {
+ xbzrle_counters.encoding_rate = unencoded_size / encoded_size;
+ }
+ rs->xbzrle_pages_prev = xbzrle_counters.pages;
+ rs->xbzrle_bytes_prev = xbzrle_counters.bytes;
}
if (migrate_use_compression()) {