Skip to content

Commit

Permalink
migration/xbzrle: add encoding rate
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Wei Wang <[email protected]>
Message-Id: <[email protected]>
Reviewed-by: Dr. David Alan Gilbert <[email protected]>
Signed-off-by: Dr. David Alan Gilbert <[email protected]>
  • Loading branch information
wei-w-wang authored and dagrh committed May 7, 2020
1 parent 59c59c6 commit e460a4b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
1 change: 1 addition & 0 deletions migration/migration.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
39 changes: 37 additions & 2 deletions migration/ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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()) {
Expand Down
2 changes: 2 additions & 0 deletions monitor/hmp-cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->xbzrle_cache->cache_miss);
monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n",
info->xbzrle_cache->cache_miss_rate);
monitor_printf(mon, "xbzrle encoding rate: %0.2f\n",
info->xbzrle_cache->encoding_rate);
monitor_printf(mon, "xbzrle overflow: %" PRIu64 "\n",
info->xbzrle_cache->overflow);
}
Expand Down
5 changes: 4 additions & 1 deletion qapi/migration.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,16 @@
#
# @cache-miss-rate: rate of cache miss (since 2.1)
#
# @encoding-rate: rate of encoded bytes (since 5.1)
#
# @overflow: number of overflows
#
# Since: 1.2
##
{ 'struct': 'XBZRLECacheStats',
'data': {'cache-size': 'int', 'bytes': 'int', 'pages': 'int',
'cache-miss': 'int', 'cache-miss-rate': 'number',
'overflow': 'int' } }
'encoding-rate': 'number', 'overflow': 'int' } }

##
# @CompressionStats:
Expand Down Expand Up @@ -337,6 +339,7 @@
# "pages":2444343,
# "cache-miss":2244,
# "cache-miss-rate":0.123,
# "encoding-rate":80.1,
# "overflow":34434
# }
# }
Expand Down

0 comments on commit e460a4b

Please sign in to comment.