From: Orit Wasserman <owasserm@redhat.com>
To: Luiz Capitulino <lcapitulino@redhat.com>
Cc: Petter Svard <petters@cs.umu.se>,
Aidan Shribman <aidan.shribman@sap.com>,
Benoit Hudzia <benoit.hudzia@sap.com>,
qemu-devel@nongnu.org, Juan Quintela <quintela@redhat.com>
Subject: Re: [Qemu-devel] [PATCH 21/22] Add XBZRLE statistics
Date: Tue, 24 Jul 2012 09:32:56 +0300 [thread overview]
Message-ID: <500E4198.7070903@redhat.com> (raw)
In-Reply-To: <20120723163304.7d740b9d@doriath.home>
On 07/23/2012 10:33 PM, Luiz Capitulino wrote:
> On Fri, 13 Jul 2012 09:23:43 +0200
> Juan Quintela <quintela@redhat.com> wrote:
>
>> From: Orit Wasserman <owasserm@redhat.com>
>>
>> Signed-off-by: Benoit Hudzia <benoit.hudzia@sap.com>
>> Signed-off-by: Petter Svard <petters@cs.umu.se>
>> Signed-off-by: Aidan Shribman <aidan.shribman@sap.com>
>> Signed-off-by: Orit Wasserman <owasserm@redhat.com>
>> Signed-off-by: Juan Quintela <quintela@redhat.com>
>> ---
>> arch_init.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> hmp.c | 13 +++++++++++
>> migration.c | 49 ++++++++++++++++++++++++++++++++++++++++
>> migration.h | 9 ++++++++
>> qapi-schema.json | 37 +++++++++++++++++++++++++-----
>> qmp-commands.hx | 35 ++++++++++++++++++++++++++++-
>> 6 files changed, 203 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch_init.c b/arch_init.c
>> index d972d84..ab3fb2c 100644
>> --- a/arch_init.c
>> +++ b/arch_init.c
>> @@ -202,6 +202,64 @@ int64_t xbzrle_cache_resize(int64_t new_size)
>> return pow2floor(new_size);
>> }
>>
>> +/* accounting for migration statistics */
>> +typedef struct AccountingInfo {
>> + uint64_t dup_pages;
>> + uint64_t norm_pages;
>> + uint64_t xbzrle_bytes;
>> + uint64_t xbzrle_pages;
>> + uint64_t xbzrle_cache_miss;
>> + uint64_t iterations;
>> + uint64_t xbzrle_overflows;
>> +} AccountingInfo;
>> +
>> +static AccountingInfo acct_info;
>> +
>> +static void acct_clear(void)
>> +{
>> + memset(&acct_info, 0, sizeof(acct_info));
>> +}
>> +
>> +uint64_t dup_mig_bytes_transferred(void)
>> +{
>> + return acct_info.dup_pages * TARGET_PAGE_SIZE;
>> +}
>> +
>> +uint64_t dup_mig_pages_transferred(void)
>> +{
>> + return acct_info.dup_pages;
>> +}
>> +
>> +uint64_t norm_mig_bytes_transferred(void)
>> +{
>> + return acct_info.norm_pages * TARGET_PAGE_SIZE;
>> +}
>> +
>> +uint64_t norm_mig_pages_transferred(void)
>> +{
>> + return acct_info.norm_pages;
>> +}
>> +
>> +uint64_t xbzrle_mig_bytes_transferred(void)
>> +{
>> + return acct_info.xbzrle_bytes;
>> +}
>> +
>> +uint64_t xbzrle_mig_pages_transferred(void)
>> +{
>> + return acct_info.xbzrle_pages;
>> +}
>> +
>> +uint64_t xbzrle_mig_pages_cache_miss(void)
>> +{
>> + return acct_info.xbzrle_cache_miss;
>> +}
>> +
>> +uint64_t xbzrle_mig_pages_overflow(void)
>> +{
>> + return acct_info.xbzrle_overflows;
>> +}
>> +
>> static void save_block_hdr(QEMUFile *f, RAMBlock *block, ram_addr_t offset,
>> int cont, int flag)
>> {
>> @@ -230,6 +288,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>> if (!cache_is_cached(XBZRLE.cache, current_addr)) {
>> cache_insert(XBZRLE.cache, current_addr,
>> g_memdup(current_data, TARGET_PAGE_SIZE));
>> + acct_info.xbzrle_cache_miss++;
>> return -1;
>> }
>>
>> @@ -244,6 +303,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>> return 0;
>> } else if (encoded_len == -1) {
>> DPRINTF("Overflow\n");
>> + acct_info.xbzrle_overflows++;
>> /* update data in the cache */
>> memcpy(prev_cached_page, current_data, TARGET_PAGE_SIZE);
>> return -1;
>> @@ -263,7 +323,9 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,
>> qemu_put_byte(f, hdr.xh_flags);
>> qemu_put_be16(f, hdr.xh_len);
>> qemu_put_buffer(f, XBZRLE.encoded_buf, encoded_len);
>> + acct_info.xbzrle_pages++;
>> bytes_sent = encoded_len + sizeof(hdr);
>> + acct_info.xbzrle_bytes += bytes_sent;
>>
>> return bytes_sent;
>> }
>> @@ -303,6 +365,7 @@ static int ram_save_block(QEMUFile *f)
>> p = memory_region_get_ram_ptr(mr) + offset;
>>
>> if (is_dup_page(p)) {
>> + acct_info.dup_pages++;
>> save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_COMPRESS);
>> qemu_put_byte(f, *p);
>> bytes_sent = 1;
>> @@ -318,6 +381,7 @@ static int ram_save_block(QEMUFile *f)
>> save_block_hdr(f, block, offset, cont, RAM_SAVE_FLAG_PAGE);
>> qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
>> bytes_sent = TARGET_PAGE_SIZE;
>> + acct_info.norm_pages++;
>> }
>>
>> /* if page is unmodified, continue to the next */
>> @@ -437,6 +501,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
>> return -1;
>> }
>> XBZRLE.encoded_buf = g_malloc0(TARGET_PAGE_SIZE);
>> + acct_clear();
>> }
>>
>> QLIST_FOREACH(block, &ram_list.blocks, next) {
>> @@ -484,6 +549,7 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
>> break;
>> }
>> bytes_transferred += bytes_sent;
>> + acct_info.iterations++;
>> /* we want to check in the 1st loop, just in case it was the 1st time
>> and we had to sync the dirty bitmap.
>> qemu_get_clock_ns() is a bit expensive, so we only check each some
>> diff --git a/hmp.c b/hmp.c
>> index 99ad00a..0d7333b 100644
>> --- a/hmp.c
>> +++ b/hmp.c
>> @@ -168,6 +168,19 @@ void hmp_info_migrate(Monitor *mon)
>> info->disk->total >> 10);
>> }
>>
>> + if (info->has_cache) {
>> + monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
>> + info->cache->cache_size);
>> + monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
>> + info->cache->xbzrle_bytes >> 10);
>> + monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
>> + info->cache->xbzrle_pages);
>> + monitor_printf(mon, "xbzrle cache miss: %" PRIu64 "\n",
>> + info->cache->xbzrle_cache_miss);
>> + monitor_printf(mon, "xbzrle overflow : %" PRIu64 "\n",
>> + info->cache->xbzrle_overflow);
>> + }
>> +
>> qapi_free_MigrationInfo(info);
>> }
>>
>> diff --git a/migration.c b/migration.c
>> index d134bf6..e11f451 100644
>> --- a/migration.c
>> +++ b/migration.c
>> @@ -137,6 +137,17 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>> info->capabilities->value->state = s->enabled_capabilities[i];
>> info->capabilities->next = NULL;
>> }
>> +
>> + /* display xbzrle cache size */
>> + if (migrate_use_xbzrle()) {
>> + info->has_cache = true;
>> + info->cache = g_malloc0(sizeof(*info->cache));
>> + info->cache->cache_size = migrate_xbzrle_cache_size();
>> + info->cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
>> + info->cache->xbzrle_pages = xbzrle_mig_pages_transferred();
>> + info->cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
>> + info->cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
>> + }
>
> Why do you need this in MIG_STATE_SETUP? I think having it only in
> MIG_STATE_ACTIVE is enough (and probably that's what we want).
you are right we just need the cache size (which can be set before the migration).
>
>> break;
>> case MIG_STATE_ACTIVE:
>> for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
>> @@ -161,6 +172,8 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>> info->ram->total = ram_bytes_total();
>> info->ram->total_time = qemu_get_clock_ms(rt_clock)
>> - s->total_time;
>> + info->ram->duplicate = dup_mig_pages_transferred();
>> + info->ram->normal = norm_mig_pages_transferred();
>
> Can we do this extension in a different patch?
ok
>
>>
>> if (blk_mig_active()) {
>> info->has_disk = true;
>> @@ -169,6 +182,16 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>> info->disk->remaining = blk_mig_bytes_remaining();
>> info->disk->total = blk_mig_bytes_total();
>> }
>> +
>> + if (migrate_use_xbzrle()) {
>> + info->has_cache = true;
>> + info->cache = g_malloc0(sizeof(*info->cache));
>> + info->cache->cache_size = migrate_xbzrle_cache_size();
>> + info->cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
>> + info->cache->xbzrle_pages = xbzrle_mig_pages_transferred();
>> + info->cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
>> + info->cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
>> + }
>> break;
>> case MIG_STATE_COMPLETED:
>> for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
>> @@ -183,6 +206,32 @@ MigrationInfo *qmp_query_migrate(Error **errp)
>> info->capabilities->next = NULL;
>> }
>>
>> + info->has_ram = true;
>> + info->ram = g_malloc0(sizeof(*info->ram));
>> + info->ram->transferred = ram_bytes_transferred();
>> + info->ram->remaining = ram_bytes_remaining();
>> + info->ram->total = ram_bytes_total();
>> + info->ram->duplicate = dup_mig_pages_transferred();
>> + info->ram->normal = norm_mig_pages_transferred();
>
> This hunk is probably bad copy & paste, as this code already exists.
looks like a bad merge I will remove it
>
>> +
>> + if (blk_mig_active()) {
>> + info->has_disk = true;
>> + info->disk = g_malloc0(sizeof(*info->disk));
>> + info->disk->transferred = blk_mig_bytes_transferred();
>> + info->disk->remaining = blk_mig_bytes_remaining();
>> + info->disk->total = blk_mig_bytes_total();
>> + }
>
> Why are you doing this, bad copy & paste too?
looks like a bad merge I will remove it
>
>> +
>> + if (migrate_use_xbzrle()) {
>> + info->has_cache = true;
>> + info->cache = g_malloc0(sizeof(*info->cache));
>> + info->cache->cache_size = migrate_xbzrle_cache_size();
>> + info->cache->xbzrle_bytes = xbzrle_mig_bytes_transferred();
>> + info->cache->xbzrle_pages = xbzrle_mig_pages_transferred();
>> + info->cache->xbzrle_cache_miss = xbzrle_mig_pages_cache_miss();
>> + info->cache->xbzrle_overflow = xbzrle_mig_pages_overflow();
>> + }
>> +
>> info->has_status = true;
>> info->status = g_strdup("completed");
>>
>> diff --git a/migration.h b/migration.h
>> index 337e225..a9852fc 100644
>> --- a/migration.h
>> +++ b/migration.h
>> @@ -87,6 +87,15 @@ uint64_t ram_bytes_total(void);
>>
>> extern SaveVMHandlers savevm_ram_handlers;
>>
>> +uint64_t dup_mig_bytes_transferred(void);
>> +uint64_t dup_mig_pages_transferred(void);
>> +uint64_t norm_mig_bytes_transferred(void);
>> +uint64_t norm_mig_pages_transferred(void);
>> +uint64_t xbzrle_mig_bytes_transferred(void);
>> +uint64_t xbzrle_mig_pages_transferred(void);
>> +uint64_t xbzrle_mig_pages_overflow(void);
>> +uint64_t xbzrle_mig_pages_cache_miss(void);
>> +
>> /**
>> * @migrate_add_blocker - prevent migration from proceeding
>> *
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index a0f0f95..961810b 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -264,11 +264,35 @@
>> # migration has ended, it returns the total migration
>> # time. (since 1.2)
>> #
>> -# Since: 0.14.0.
>> +# @duplicate: #optional, number of duplicate pages
>> +#
>> +# @normal : #optional, number of normal pages
>> +#
>> +# Since: 0.14.0, 'duplicate' and 'normal' since 1.2
>
> Please, put 'since' in the same line of the field, like this:
>
> @normal : #optional, number of normal pages (since 1.2)
ok
>
>> ##
>> { 'type': 'MigrationStats',
>> 'data': {'transferred': 'int', 'remaining': 'int', 'total': 'int' ,
>> - 'total_time': 'int' } }
>> + 'total_time': 'int', '*duplicate': 'int', '*normal': 'int' } }
>> +##
>> +# @CacheStats
>
> This is specific to xbzrle, right? So this should be called XBZRLECacheStats,
> or something.
sure
>
>> +#
>> +# Detailed XBZRLE migration cache statistics
>> +#
>> +# @cache_size: XBZRLE cache size
>> +#
>> +# @xbzrle_bytes: amount of bytes already transferred to the target VM
>> +#
>> +# @xbzrle_pages: amount of pages transferred to the target VM
>> +#
>> +# @xbzrle_cache_miss: number of cache miss
>> +#
>> +# @xbzrle_overflow: number of overflows
>> +#
>> +# Since: 1.2
>> +##
>> +{ 'type': 'CacheStats',
>> + 'data': {'cache-size': 'int', 'xbzrle-bytes': 'int', 'xbzrle-pages': 'int',
>> + 'xbzrle-cache-miss': 'int', 'xbzrle-overflow': 'int' } }
>>
>> ##
>> # @MigrationInfo
>> @@ -291,13 +315,16 @@
>> # @capabilities: #optional a list describing all the migration capabilities
>> # state
>> #
>> -# Since: 0.14.0, 'capabilities' since 1.2
>> +# @cache: #optional @MigrationStats containing detailed XBZRLE migration
>> +# statistics
>
> xbzrle-cache.
ok
Thanks,
Orit
>
>> +#
>> +# Since: 0.14.0, 'capabilities' and 'cache' since 1.2
>> ##
>> { 'type': 'MigrationInfo',
>> 'data': {'*status': 'str', '*ram': 'MigrationStats',
>> '*disk': 'MigrationStats',
>> - '*capabilities': ['MigrationCapabilityInfo']} }
>> -
>> + '*capabilities': ['MigrationCapabilityInfo'],
>> + '*cache': 'CacheStats'} }
>> ##
>> # @query-migrate
>> #
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index a3d57ce..34d4675 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -2093,6 +2093,8 @@ The main json-object contains the following:
>> - "transferred": amount transferred (json-int)
>> - "remaining": amount remaining (json-int)
>> - "total": total (json-int)
>> + - "duplicate": number of duplicated pages (json-int)
>> + - "normal" : number of normal pages transferred (json-int)
>> - "disk": only present if "status" is "active" and it is a block migration,
>> it is a json-object with the following disk information (in bytes):
>> - "transferred": amount transferred (json-int)
>> @@ -2100,10 +2102,17 @@ The main json-object contains the following:
>> - "total": total (json-int)
>> - "capabilities": migration capabilities state
>> - "xbzrle" : XBZRLE state (json-bool)
>> +- "cache": only present if "status" and XBZRLE is active.
>> + It is a json-object with the following XBZRLE information:
>> + - "cache-size": XBZRLE cache size
>> + - "xbzrle-bytes": total XBZRLE bytes transferred
>> + - "xbzrle-pages": number of XBZRLE compressed pages
>> + - "cache-miss": number of cache misses
>> + - "overflow": number of XBZRLE overflows
>> +
>> Examples:
>>
>> 1. Before the first migration
>> -
>> -> { "execute": "query-migrate" }
>> <- { "return": {
>> "capabilities" : [ { "capability" : "xbzrle", "state" : false } ]
>> @@ -2164,6 +2173,30 @@ Examples:
>> }
>> }
>>
>> +6. Migration is being performed and XBZRLE is active:
>> +
>> +-> { "execute": "query-migrate" }
>> +<- {
>> + "return":{
>> + "status":"active",
>> + "capabilities" : [ { "capability": "xbzrle", "state" : true } ],
>> + "ram":{
>> + "total":1057024,
>> + "remaining":1053304,
>> + "transferred":3720,
>> + "duplicate": 10,
>> + "normal" : 3333
>> + },
>> + "cache":{
>> + "cache-size": 1024
>> + "xbzrle-transferred":20971520,
>> + "xbzrle-pages":2444343,
>> + "xbzrle-cache-miss":2244,
>> + "xbzrle-overflow":34434
>> + }
>> + }
>> + }
>> +
>> EQMP
>>
>> {
>
next prev parent reply other threads:[~2012-07-24 6:33 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-13 7:23 [Qemu-devel] [PATCH 00/22] Migration next Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 01/22] savevm: Use a struct to pass all handlers Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 02/22] savevm: Live migration handlers register the struct directly Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 03/22] savevm: remove SaveSetParamsHandler Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 04/22] savevm: remove SaveLiveStateHandler Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 05/22] savevm: Refactor cancel operation in its own operation Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 06/22] savevm: introduce is_active method Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 07/22] savevm: split save_live_setup from save_live_state Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 08/22] savevm: split save_live into stage2 and stage3 Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 09/22] ram: save_live_setup() don't need to sent pages Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 10/22] ram: save_live_complete() only do one loop Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 11/22] ram: iterate phase Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 12/22] ram: save_live_setup() we don't need to synchronize the dirty bitmap Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 13/22] Add migration capabilities Juan Quintela
2012-07-23 18:23 ` Luiz Capitulino
2012-07-23 19:30 ` Eric Blake
2012-07-24 6:25 ` Orit Wasserman
2012-07-24 12:50 ` Luiz Capitulino
2012-07-24 17:06 ` Orit Wasserman
2012-07-24 18:17 ` Luiz Capitulino
2012-07-25 13:05 ` Orit Wasserman
2012-07-25 13:11 ` Luiz Capitulino
2012-07-25 13:33 ` Orit Wasserman
2012-07-13 7:23 ` [Qemu-devel] [PATCH 14/22] Add XBZRLE documentation Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 15/22] Add cache handling functions Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 16/22] Add uleb encoding/decoding functions Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 17/22] Change ram_save_block to return -1 if there are no more changes Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 18/22] Add xbzrle_encode_buffer and xbzrle_decode_buffer functions Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 19/22] Add XBZRLE to ram_save_block and ram_save_live Juan Quintela
2012-07-13 7:23 ` [Qemu-devel] [PATCH 20/22] Add migrate_set_cachesize command Juan Quintela
2012-07-23 19:21 ` Luiz Capitulino
2012-07-13 7:23 ` [Qemu-devel] [PATCH 21/22] Add XBZRLE statistics Juan Quintela
2012-07-23 19:33 ` Luiz Capitulino
2012-07-24 6:32 ` Orit Wasserman [this message]
2012-07-13 7:23 ` [Qemu-devel] [PATCH 22/22] ram: save live optimization Juan Quintela
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=500E4198.7070903@redhat.com \
--to=owasserm@redhat.com \
--cc=aidan.shribman@sap.com \
--cc=benoit.hudzia@sap.com \
--cc=lcapitulino@redhat.com \
--cc=petters@cs.umu.se \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.