Re: [PATCH v1 2/2] migration/xbzrle: add encoding rate

2020-04-20 Thread Wei Wang

On 04/20/2020 10:53 PM, Eric Blake wrote:

On 4/19/20 10:06 PM, Wei Wang wrote:

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 
Signed-off-by: Wei Wang 
---


In addition to Dan's review comments,


+++ b/qapi/migration.json
@@ -70,6 +70,8 @@
  #
  # @cache-miss-rate: rate of cache miss (since 2.1)
  #
+# @encoding-rate: rate of cache miss


This is missing a '(since 5.1)' tag.


OK, will add it, thanks.

Best,
Wei



Re: [PATCH v1 2/2] migration/xbzrle: add encoding rate

2020-04-20 Thread Eric Blake

On 4/19/20 10:06 PM, Wei Wang wrote:

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 
Signed-off-by: Wei Wang 
---


In addition to Dan's review comments,


+++ b/qapi/migration.json
@@ -70,6 +70,8 @@
  #
  # @cache-miss-rate: rate of cache miss (since 2.1)
  #
+# @encoding-rate: rate of cache miss


This is missing a '(since 5.1)' tag.


+#
  # @overflow: number of overflows
  #
  # Since: 1.2
@@ -77,7 +79,7 @@
  { 'struct': 'XBZRLECacheStats',
'data': {'cache-size': 'int', 'encoded_size': 'int', 'pages': 'int',
 'cache-miss': 'int', 'cache-miss-rate': 'number',
-   'overflow': 'int' } }
+   'encoding-rate': 'number', 'overflow': 'int' } }
  
  ##

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

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v1 2/2] migration/xbzrle: add encoding rate

2020-04-20 Thread Daniel P . Berrangé
On Mon, Apr 20, 2020 at 11:06:43AM +0800, Wei Wang wrote:
> 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 
> Signed-off-by: Wei Wang 
> ---
>  migration/migration.c |  1 +
>  migration/ram.c   | 31 +--
>  monitor/hmp-cmds.c|  2 ++
>  qapi/migration.json   |  5 -
>  slirp |  2 +-
>  5 files changed, 37 insertions(+), 4 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index 8e7ee0d76b..84a556a4ac 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -930,6 +930,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 bca5878f25..c87c38ec80 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 encoded bytes since the beginning of the period */
> +uint64_t encoded_size_prev;
>  
>  /* compression statistics since the beginning of the period */
>  /* amount of count that no free thread to compress data */
> @@ -696,6 +700,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 */
> @@ -736,7 +752,6 @@ static int save_xbzrle_page(RAMState *rs, uint8_t 
> **current_data,
>  qemu_put_be16(rs->f, encoded_size);
>  qemu_put_buffer(rs->f, XBZRLE.encoded_buf, encoded_size);
>  bytes_xbzrle += encoded_size + 1 + 2;
> -xbzrle_counters.pages++;
>  xbzrle_counters.encoded_size += encoded_size;
>  ram_counters.transferred += bytes_xbzrle;
>  
> @@ -859,7 +874,7 @@ uint64_t ram_get_total_transferred_pages(void)
>  static void migration_update_rates(RAMState *rs, int64_t end_time)
>  {
>  uint64_t page_count = rs->target_page_count - rs->target_page_count_prev;
> -double compressed_size;
> +double compressed_size, encoded_size, unencoded_size;
>  
>  /* calculate period counters */
>  ram_counters.dirty_pages_rate = rs->num_dirty_pages_period * 1000
> @@ -873,6 +888,18 @@ static void migration_update_rates(RAMState *rs, int64_t 
> end_time)
>  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.encoded_size - rs->encoded_size_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->encoded_size_prev = xbzrle_counters.encoded_size;
>  }
>  
>  if (migrate_use_compression()) {
> diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
> index 6d3b35ca64..07f41e582f 100644
> --- a/monitor/hmp-cmds.c
> +++ b/monitor/hmp-cmds.c
> @@ -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",
> 

[PATCH v1 2/2] migration/xbzrle: add encoding rate

2020-04-19 Thread Wei Wang
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 
Signed-off-by: Wei Wang 
---
 migration/migration.c |  1 +
 migration/ram.c   | 31 +--
 monitor/hmp-cmds.c|  2 ++
 qapi/migration.json   |  5 -
 slirp |  2 +-
 5 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/migration/migration.c b/migration/migration.c
index 8e7ee0d76b..84a556a4ac 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -930,6 +930,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 bca5878f25..c87c38ec80 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 encoded bytes since the beginning of the period */
+uint64_t encoded_size_prev;
 
 /* compression statistics since the beginning of the period */
 /* amount of count that no free thread to compress data */
@@ -696,6 +700,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 */
@@ -736,7 +752,6 @@ static int save_xbzrle_page(RAMState *rs, uint8_t 
**current_data,
 qemu_put_be16(rs->f, encoded_size);
 qemu_put_buffer(rs->f, XBZRLE.encoded_buf, encoded_size);
 bytes_xbzrle += encoded_size + 1 + 2;
-xbzrle_counters.pages++;
 xbzrle_counters.encoded_size += encoded_size;
 ram_counters.transferred += bytes_xbzrle;
 
@@ -859,7 +874,7 @@ uint64_t ram_get_total_transferred_pages(void)
 static void migration_update_rates(RAMState *rs, int64_t end_time)
 {
 uint64_t page_count = rs->target_page_count - rs->target_page_count_prev;
-double compressed_size;
+double compressed_size, encoded_size, unencoded_size;
 
 /* calculate period counters */
 ram_counters.dirty_pages_rate = rs->num_dirty_pages_period * 1000
@@ -873,6 +888,18 @@ static void migration_update_rates(RAMState *rs, int64_t 
end_time)
 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.encoded_size - rs->encoded_size_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->encoded_size_prev = xbzrle_counters.encoded_size;
 }
 
 if (migrate_use_compression()) {
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 6d3b35ca64..07f41e582f 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -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);
 }
diff --git