In sampling mode, a new metric is collected and reported: number of pages entirely filled with zeroes.
Signed-off-by: Andrei Gudkov <gudkov.and...@huawei.com> --- migration/dirtyrate.c | 40 +++++++++++++++++++++++++++++++++++----- migration/dirtyrate.h | 1 + qapi/migration.json | 4 ++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index 4491bbe91a..55ef69927e 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -258,6 +258,9 @@ static struct DirtyRateInfo *query_dirty_rate_info(void) info->n_sampled_pages = DirtyStat.page_sampling.n_sampled_pages; info->has_n_sampled_pages = true; + info->n_zero_pages = DirtyStat.page_sampling.n_zero_pages; + info->has_n_zero_pages = true; + for (i = 0; i < DirtyStat.page_sampling.n_readings; i++) { DirtyReading *dr = &DirtyStat.page_sampling.readings[i]; QAPI_LIST_APPEND(periods_tail, dr->period); @@ -291,6 +294,7 @@ static void init_dirtyrate_stat(int64_t start_time, case DIRTY_RATE_MEASURE_MODE_PAGE_SAMPLING: DirtyStat.page_sampling.n_total_pages = 0; DirtyStat.page_sampling.n_sampled_pages = 0; + DirtyStat.page_sampling.n_zero_pages = 0; DirtyStat.page_sampling.n_readings = 0; DirtyStat.page_sampling.readings = g_try_malloc0_n(MAX_DIRTY_READINGS, sizeof(DirtyReading)); @@ -319,6 +323,7 @@ static void cleanup_dirtyrate_stat(struct DirtyRateConfig config) /* * Compute hash of a single page of size TARGET_PAGE_SIZE. + * If ptr is NULL, then compute hash of a page entirely filled with zeros. */ static uint32_t compute_page_hash(void *ptr) { @@ -331,11 +336,20 @@ static uint32_t compute_page_hash(void *ptr) v2 = QEMU_XXHASH_SEED + XXH_PRIME64_2; v3 = QEMU_XXHASH_SEED + 0; v4 = QEMU_XXHASH_SEED - XXH_PRIME64_1; - for (i = 0; i < TARGET_PAGE_SIZE / 8; i += 4) { - v1 = XXH64_round(v1, p[i + 0]); - v2 = XXH64_round(v2, p[i + 1]); - v3 = XXH64_round(v3, p[i + 2]); - v4 = XXH64_round(v4, p[i + 3]); + if (ptr) { + for (i = 0; i < TARGET_PAGE_SIZE / 8; i += 4) { + v1 = XXH64_round(v1, p[i + 0]); + v2 = XXH64_round(v2, p[i + 1]); + v3 = XXH64_round(v3, p[i + 2]); + v4 = XXH64_round(v4, p[i + 3]); + } + } else { + for (i = 0; i < TARGET_PAGE_SIZE / 8; i += 4) { + v1 = XXH64_round(v1, 0); + v2 = XXH64_round(v2, 0); + v3 = XXH64_round(v3, 0); + v4 = XXH64_round(v4, 0); + } } res = XXH64_mergerounds(v1, v2, v3, v4); res += TARGET_PAGE_SIZE; @@ -343,6 +357,17 @@ static uint32_t compute_page_hash(void *ptr) return (uint32_t)(res & UINT32_MAX); } +static uint32_t get_zero_page_hash(void) +{ + static uint32_t hash; + static int is_computed; + + if (!is_computed) { + hash = compute_page_hash(NULL); + is_computed = 1; + } + return hash; +} /* * get hash result for the sampled memory with length of TARGET_PAGE_SIZE @@ -364,6 +389,7 @@ static bool save_ramblock_hash(struct RamblockDirtyInfo *info) unsigned int sample_pages_count; int i; GRand *rand; + uint32_t zero_page_hash = get_zero_page_hash(); sample_pages_count = info->sample_pages_count; @@ -393,6 +419,9 @@ static bool save_ramblock_hash(struct RamblockDirtyInfo *info) info->hash_result[i] = get_ramblock_vfn_hash(info, info->sample_page_vfn[i]); DirtyStat.page_sampling.n_sampled_pages++; + if (info->hash_result[i] == zero_page_hash) { + DirtyStat.page_sampling.n_zero_pages++; + } } g_rand_free(rand); @@ -891,6 +920,7 @@ void hmp_info_dirty_rate(Monitor *mon, const QDict *qdict) monitor_printf(mon, "Page count (page size %d):\n", TARGET_PAGE_SIZE); monitor_printf(mon, " Total: %"PRIi64"\n", info->n_total_pages); monitor_printf(mon, " Sampled: %"PRIi64"\n", info->n_sampled_pages); + monitor_printf(mon, " Zero: %"PRIi64"\n", info->n_zero_pages); int64List *periods = info->periods; int64List *n_dirty_pages = info->n_dirty_pages; while (periods) { diff --git a/migration/dirtyrate.h b/migration/dirtyrate.h index 7a97e2b076..e2af72fb8c 100644 --- a/migration/dirtyrate.h +++ b/migration/dirtyrate.h @@ -80,6 +80,7 @@ typedef struct DirtyReading { typedef struct SampleVMStat { int64_t n_total_pages; /* total number of pages */ int64_t n_sampled_pages; /* number of sampled pages */ + int64_t n_zero_pages; /* number of observed zero pages */ int64_t n_readings; DirtyReading *readings; } SampleVMStat; diff --git a/qapi/migration.json b/qapi/migration.json index f818f51e0e..2c48a9ef80 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1811,6 +1811,9 @@ # # @n-sampled-pages: [page-sampling] number of sampled VM pages (since 8.1) # +# @n-zero-pages: [page-sampling] number of observed all-zero pages among all +# sampled pages (since 8.1) +# # @periods: [page-sampling] array of time periods expressed in milliseconds # for which dirty-sample measurements were collected (since 8.1) # @@ -1834,6 +1837,7 @@ 'page-size': 'int64', '*n-total-pages': 'int64', '*n-sampled-pages': 'int64', + '*n-zero-pages': 'int64', '*periods': ['int64'], '*n-dirty-pages': ['int64'] } } -- 2.30.2