qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 3/4] migration/calc-dirty-rate: added n-zero-pages metric


From: Andrei Gudkov
Subject: [PATCH v2 3/4] migration/calc-dirty-rate: added n-zero-pages metric
Date: Thu, 27 Apr 2023 15:42:59 +0300

In sampling mode, a new metric is collected and reported:
number of pages entirely filled with zeroes.

Signed-off-by: Andrei Gudkov <gudkov.andrei@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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]