生活随笔
收集整理的這篇文章主要介紹了
QEMU脏页速率计算原理
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄 背景基礎(chǔ) 數(shù)據(jù)結(jié)構(gòu) 邏輯框架 dirty-bitmap 計(jì)算原理 數(shù)據(jù)結(jié)構(gòu) 實(shí)現(xiàn)流程 臟頁(yè)數(shù)統(tǒng)計(jì) 速率計(jì)算 dirty-ring 計(jì)算原理 數(shù)據(jù)結(jié)構(gòu) 實(shí)現(xiàn)流程 臟頁(yè)數(shù)統(tǒng)計(jì) 速率計(jì)算
背景基礎(chǔ)
臟頁(yè)速率在QEMU中定義為虛機(jī)單位時(shí)間內(nèi)產(chǎn)生臟內(nèi)存頁(yè)的速率,用于描述虛機(jī)內(nèi)存變化的快慢,臟頁(yè)速率越大,虛機(jī)內(nèi)存變化越快,遷移時(shí)花費(fèi)的時(shí)間就越多。臟頁(yè)速率計(jì)算公式為:
dirtyrate = increased_memory / meaurement_time
臟頁(yè)速率計(jì)算的關(guān)鍵是如何獲取單位時(shí)間內(nèi)虛擬機(jī)新增的臟頁(yè)數(shù),不同的獲取方式有不同的速率計(jì)算實(shí)現(xiàn),QEMU已經(jīng)實(shí)現(xiàn)了一種計(jì)算方式,即抽樣,抽樣方式假設(shè)虛機(jī)讀寫內(nèi)存的區(qū)間是均勻隨機(jī)的,但實(shí)際情況并非如此,因此存在一定誤差。除抽樣方式外,還有兩種新的臟頁(yè)速率計(jì)算實(shí)現(xiàn)(預(yù)計(jì)在6.1版本合入QEMU主線),分別是dirty-bitmap和dirty-ring。dirty-bitmap是一種新的臟頁(yè)速率實(shí)現(xiàn),通過(guò)查詢dirty-bitmap,獲取一段時(shí)間內(nèi)新增的臟頁(yè)數(shù),計(jì)算臟頁(yè)速率。dirty-ring同樣是一種新的臟頁(yè)速率實(shí)現(xiàn),通過(guò)查詢vcpu上臟頁(yè)數(shù),獲取一段時(shí)間內(nèi)vcpu上新增的臟頁(yè)數(shù),計(jì)算vcpu的臟頁(yè)速率,從而得到整個(gè)虛機(jī)的臟頁(yè)速率。
數(shù)據(jù)結(jié)構(gòu)
臟頁(yè)速率統(tǒng)計(jì)信息由數(shù)據(jù)結(jié)構(gòu)struct DirtyRateStat表示,因速率計(jì)算方式不同,需要的統(tǒng)計(jì)信息也不同,對(duì)于抽樣的方式,描述統(tǒng)計(jì)信息的結(jié)構(gòu)體是SampleVMStat,對(duì)于dirty-ring的方式,描述統(tǒng)計(jì)信息的結(jié)構(gòu)體是VcpuStat,而dirty-bitmap方式的統(tǒng)計(jì)信息比較簡(jiǎn)單,就是一個(gè)全局變量total_dirty_pages,它用于記錄臟頁(yè)數(shù)量。數(shù)據(jù)結(jié)構(gòu)定義在migration/dirtyrate.h中。
/* 抽樣方式的統(tǒng)計(jì)信息 */
typedef struct SampleVMStat {uint64_t total_dirty_samples; /* total dirty sampled page */uint64_t total_sample_count; /* total sampled pages */uint64_t total_block_mem_MB; /* size of total sampled pages in MB */
} SampleVMStat;struct DirtyRateStat {/* 保存虛擬機(jī)的臟頁(yè)速率 */int64_t dirty_rate; /* dirty rate in MB/s */int64_t start_time; /* calculation start time in units of second */int64_t calc_time; /* time duration of two sampling in units of second */uint64_t sample_pages; /* sample pages per GB */union {/* 保存抽樣方式的統(tǒng)計(jì)信息 */SampleVMStat page_sampling;/* 保存dirty-ring方式的統(tǒng)計(jì)信息 */VcpuStat dirty_ring;};
};
/* 記錄測(cè)量前后內(nèi)存的臟頁(yè)數(shù),兩者的差值為新增的臟頁(yè)數(shù) */
typedef struct DirtyPageRecord {uint64_t start_pages;uint64_t end_pages;
} DirtyPageRecord;
邏輯框架
臟頁(yè)速率計(jì)算對(duì)外提供了兩個(gè)命令,用于計(jì)算和查詢,分別是qmp_calc_dirty_rate和qmp_query_dirty_rate,其實(shí)現(xiàn)邏輯比較簡(jiǎn)單,如下圖所示,用戶通過(guò)qmp_calc_dirty_rate發(fā)起臟頁(yè)速率計(jì)算,qemu單獨(dú)啟動(dòng)一個(gè)get_dirtyrate線程用于計(jì)算臟頁(yè)速率,完成后將結(jié)果存放到全局變量DirtyStat中,然后線程退出。需要查詢臟頁(yè)速率時(shí),通過(guò)qmp_query_dirty_rate查詢之前存放到DirtyStat中的計(jì)算結(jié)果,返回給用戶。
dirty-bitmap
計(jì)算原理
dirty-bitmap計(jì)算臟頁(yè)速率,顧名思義,是通過(guò)查詢bitmap來(lái)獲取新增的虛機(jī)臟頁(yè)數(shù)。我們知道虛機(jī)在遷移時(shí)會(huì)在每個(gè)迭代周期以slot為單位,通過(guò)kvm提供的ioctl命令字從內(nèi)核空間獲取虛擬機(jī)的新增臟頁(yè),從而得到本輪迭代需要發(fā)送的內(nèi)存頁(yè)。該ioctl命令字返回bitmap數(shù)據(jù)結(jié)構(gòu),dirty-bitmap臟頁(yè)速率的計(jì)算就基于此接口。簡(jiǎn)單講,其原理是通過(guò)調(diào)用ioctl命令獲取虛機(jī)臟頁(yè)位圖,根據(jù)位圖統(tǒng)計(jì)出臟頁(yè)數(shù)量,再除以時(shí)間,得到臟頁(yè)速率。
數(shù)據(jù)結(jié)構(gòu)
dirty-bitmap臟頁(yè)速率計(jì)算的數(shù)據(jù)結(jié)構(gòu)非常簡(jiǎn)單,只有一個(gè)用于統(tǒng)計(jì)臟頁(yè)數(shù)的全局變量,定義在migration/dirtyrate.c中:
uint64_t total_dirty_pages;
實(shí)現(xiàn)流程
臟頁(yè)數(shù)統(tǒng)計(jì)
統(tǒng)計(jì)臟頁(yè)數(shù)在memory_global_dirty_log_sync的執(zhí)行路徑中完成,memory_global_dirty_log_sync在從內(nèi)核獲取到位圖之后,會(huì)將其保存到ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION] dirty bits中,在這個(gè)過(guò)程中,我們可以統(tǒng)計(jì)臟頁(yè)數(shù),流程如下:
memory_global_dirty_log_syncmemory_region_sync_dirty_bitmaplog_sync -> kvm_log_synckvm_physical_sync_dirty_bitmap/* 從內(nèi)核獲取到slot的臟頁(yè)位圖,緩存到slot->dirty_bmap中 */kvm_slot_get_dirty_log/* 將緩存的slot->dirty_bmap保存到DIRTY_MEMORY_MIGRATION dirty bits中 */kvm_slot_sync_dirty_pagescpu_physical_memory_set_dirty_lebitmap
cpu_physical_memory_set_dirty_lebitmap負(fù)責(zé)將slot中的bitmap設(shè)置到dirty bits中,新增修改用于統(tǒng)計(jì)臟頁(yè)數(shù)量,如下:
@@ -373,6 +375,10 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,qatomic_or(&blocks[DIRTY_MEMORY_MIGRATION][idx][offset],temp);
+ if (unlikely(
+ /* 如果因?yàn)榕K頁(yè)速率計(jì)算開(kāi)啟了臟頁(yè)日志跟蹤 */
+ global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) {
+ /* 位圖中1的個(gè)數(shù)代表臟頁(yè)數(shù)量
+ * 統(tǒng)計(jì)1的個(gè)數(shù)將其加入到全局變量total_dirty_pages中 */
+ total_dirty_pages += ctpopl(temp);
+ }}if (tcg_enabled()) {
@@ -403,6 +409,9 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,for (i = 0; i < len; i++) {if (bitmap[i] != 0) {/* 逐一按long型長(zhǎng)度取出位圖,統(tǒng)計(jì)其中1的位數(shù) */c = leul_to_cpu(bitmap[i]);
+ if (unlikely(global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) {
+ total_dirty_pages += ctpopl(c);
+ }do {j = ctzl(c);c &= ~(1ul << j);
臟頁(yè)數(shù)量統(tǒng)計(jì)的實(shí)現(xiàn)在cpu_physical_memory_set_dirty_lebitmap函數(shù)中,根據(jù)逐一取出long型位圖,統(tǒng)計(jì)其為1的bit數(shù),得到臟頁(yè)數(shù)。存放到全局變量total_dirty_pages 中。
速率計(jì)算
開(kāi)始測(cè)量時(shí),獲取全局的臟頁(yè)計(jì)數(shù),保存到本地變量 根據(jù)用戶設(shè)置的測(cè)量時(shí)間,睡眠一段時(shí)間 再次獲取全局的臟頁(yè)計(jì)數(shù),保存到本地變量 獲取兩次臟頁(yè)計(jì)數(shù)的增量,得到增加的臟頁(yè)數(shù),計(jì)算增加內(nèi)存總量,得到臟頁(yè)速率
臟頁(yè)速率計(jì)算在calculate_dirtyrate_dirty_bitmap中實(shí)現(xiàn),分析如下:
static void calculate_dirtyrate_dirty_bitmap(struct DirtyRateConfig config)
{int64_t msec = 0;int64_t start_time;/* 臟頁(yè)計(jì)數(shù)本地變量,保存測(cè)量前后的臟頁(yè)數(shù)量,用于保存測(cè)量時(shí)間內(nèi)的臟頁(yè)增加數(shù)量 */DirtyPageRecord dirty_pages;/* 獲取BQL鎖 */qemu_mutex_lock_iothread();/* 開(kāi)啟臟頁(yè)記錄,將global_dirty_tracking變量的GLOBAL_DIRTY_DIRTY_RATE位置位 */memory_global_dirty_log_start(GLOBAL_DIRTY_DIRTY_RATE);/* * 高版本的內(nèi)核如果使能了KVM_DIRTY_LOG_INITIALLY_SET特性* 第一次查詢臟頁(yè)位圖時(shí)內(nèi)核會(huì)返回全1,這樣新增的臟頁(yè)數(shù)就是* 虛機(jī)所有可讀寫內(nèi)存頁(yè),這個(gè)頁(yè)數(shù)量無(wú)法用于統(tǒng)計(jì)* 因此默認(rèn)跳過(guò)第一次,臟頁(yè)查詢?cè)鲩L(zhǎng)的臟頁(yè)數(shù)量* //** 1'round of log sync may return all 1 bits with* KVM_DIRTY_LOG_INITIALLY_SET enable* skip it unconditionally and start dirty tracking* from 2'round of log sync*/memory_global_dirty_log_sync();/* * 高版本內(nèi)核可能會(huì)使能KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE特性 * 該特性在臟頁(yè)位圖查詢后不會(huì)將kvm的頁(yè)表的臟頁(yè)位清零,而是等到用戶態(tài)qemu* 發(fā)送內(nèi)存頁(yè)之后再清零,這個(gè)時(shí)間窗口內(nèi)虛機(jī)新增的臟頁(yè)不會(huì)被kvm記錄* 這里,因?yàn)槲粓D不用于遷移,所以需要在臟頁(yè)查詢后調(diào)用kvm提供的ioctl命令字* 將kvm的內(nèi)存頁(yè)的臟頁(yè)位清零,這樣kvm才能記錄臟頁(yè)* *//** reset page protect manually and unconditionally.* this make sure kvm dirty log be cleared if* KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE cap is enabled.*/dirtyrate_manual_reset_protect();qemu_mutex_unlock_iothread();/* * 至此開(kāi)始測(cè)量臟頁(yè)速率* 首先保存全局的臟頁(yè)計(jì)數(shù)total_dirty_pages到本地變量dirty_pages中* 下一次臟頁(yè)同步獲取到的位圖就是新增的內(nèi)存臟頁(yè)數(shù)* */record_dirtypages_bitmap(&dirty_pages, true);/* 獲取當(dāng)前的測(cè)量時(shí)間 */start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);DirtyStat.start_time = start_time / 1000;msec = config.sample_period_seconds * 1000;/* 睡眠config中指定的測(cè)量時(shí)間 */msec = set_sample_page_period(msec, start_time);DirtyStat.calc_time = msec / 1000;/* 睡眠醒來(lái)后觸發(fā)臟頁(yè)同步,然后停止臟頁(yè)記錄 *//** dirtyrate_global_dirty_log_stop do two things.* 1. fetch dirty bitmap from kvm* 2. stop dirty tracking*/dirtyrate_global_dirty_log_stop();/* * 臟頁(yè)同步的過(guò)程中會(huì)累加新增的臟頁(yè)數(shù)到全局臟頁(yè)計(jì)數(shù)total_dirty_pages* 這里將全局的臟頁(yè)技術(shù)total_dirty_pages保存到dirty_pages中*/record_dirtypages_bitmap(&dirty_pages, false);/* * 根據(jù)新增的臟頁(yè)數(shù)量計(jì)算臟頁(yè)速率,保存到全局變量DirtyStat中* */do_calculate_dirtyrate_bitmap(dirty_pages);
}
record_dirtypages_bitmap將全局的臟頁(yè)計(jì)數(shù)變量保存到本地變量dirty_pages,根據(jù)start標(biāo)志將其保存到對(duì)應(yīng)域
static inline void record_dirtypages_bitmap(DirtyPageRecord *dirty_pages,bool start)
{if (start) {dirty_pages->start_pages = total_dirty_pages;} else {dirty_pages->end_pages = total_dirty_pages;}
}
do_calculate_dirtyrate_bitmap根據(jù)傳入的DirtyPageRecord結(jié)構(gòu)體變量計(jì)算臟頁(yè)速率,將其保存到臟頁(yè)統(tǒng)計(jì)全局變量DirtyStat中
static void do_calculate_dirtyrate_bitmap(DirtyPageRecord dirty_pages)
{uint64_t memory_size_MB;int64_t time_s;uint64_t increased_dirty_pages =dirty_pages.end_pages - dirty_pages.start_pages;memory_size_MB = (increased_dirty_pages * TARGET_PAGE_SIZE) >> 20;time_s = DirtyStat.calc_time;DirtyStat.dirty_rate = memory_size_MB / time_s;
}
dirty-ring
計(jì)算原理
dirty-ring計(jì)算臟頁(yè)速率是基于dirty-ring的臟頁(yè)統(tǒng)計(jì)原理,它統(tǒng)計(jì)每個(gè)vcpu上新增的臟頁(yè)數(shù)量,計(jì)算每個(gè)vcpu的臟頁(yè)速率,累加所有vcpu的臟頁(yè)速率,得到整個(gè)虛機(jī)的臟頁(yè)速率
數(shù)據(jù)結(jié)構(gòu)
QEMU CPUState數(shù)據(jù)結(jié)構(gòu)中新增dirty_pages域用于統(tǒng)計(jì)每個(gè)vcpu上的臟頁(yè)數(shù)量。
/* dirty-ring方式計(jì)算臟頁(yè)速率時(shí)用于保存vcpu臟頁(yè)個(gè)數(shù) */
struct CPUState {/* 用戶態(tài)通過(guò)dirty-ring得到臟頁(yè)時(shí),默認(rèn)將臟頁(yè)數(shù)量累加到dirty_pages域 */uint64_t dirty_pages;......
}
dirty-ring方式計(jì)算臟頁(yè)速率是基于vcpu粒度,因此其結(jié)果是一個(gè)vcpu速率的鏈表。每個(gè)vcpu都對(duì)應(yīng)一個(gè)臟頁(yè)速率。
struct DirtyRateVcpu {int64_t id; /* vcpu idx */int64_t dirty_rate; /* vcpu臟頁(yè)速率 */
};
/* dirty-ring方式的統(tǒng)計(jì)信息 */
typedef struct VcpuStat {int nvcpu; /* number of vcpu *//* 保存每個(gè)vcpu的臟頁(yè)速率 */DirtyRateVcpu *rates; /* array of dirty rate for each vcpu */
} VcpuStat;
實(shí)現(xiàn)流程
臟頁(yè)數(shù)統(tǒng)計(jì)
如果使能了dirty-ring特性,qemu在啟動(dòng)虛機(jī)時(shí)會(huì)創(chuàng)建kvm-reaper線程,kvm-reaper會(huì)周期性地檢查每個(gè)vcpu上的diryt-ring,確認(rèn)是否有新增的臟頁(yè),如果有,根據(jù)臟頁(yè)地址找它在slot位圖(KVMSlot->dirty_bmap)中的位,將其置位。這個(gè)臟頁(yè)查詢的過(guò)程可以用于臟頁(yè)數(shù)統(tǒng)計(jì)。其流程如下:
kvm_dirty_ring_reaper_threadkvm_dirty_ring_reapkvm_dirty_ring_reap_locked/* 遍歷虛機(jī)的每個(gè)vcpu,檢查其上的dirty-ring是否有新增的臟頁(yè)*/CPU_FOREACH(cpu) {total += kvm_dirty_ring_reap_one(s, cpu);}
kvm_dirty_ring_reap_one檢查vcpu上的dirty-ring是否有新增臟頁(yè),如果有,將其所在slot上位圖的對(duì)應(yīng)位置位,新增的修改用于統(tǒng)計(jì)每個(gè)vcpu上的臟頁(yè)數(shù):
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -469,6 +469,7 @@ int kvm_init_vcpu(CPUState *cpu, Error **errp)cpu->kvm_fd = ret;cpu->kvm_state = s;cpu->vcpu_dirty = true;/* vcpu初始化時(shí)將臟頁(yè)計(jì)數(shù)初始化為0,之后在vcpu運(yùn)行過(guò)程中一直遞增 */
+ cpu->dirty_pages = 0;
@@ -743,6 +744,7 @@ static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)count++;}cpu->kvm_fetch_index = fetch;/* 在統(tǒng)計(jì)vcpu上dirty-ring的新增臟頁(yè)時(shí),如果有新增臟頁(yè)* 在標(biāo)記完位圖之后,將新增的臟頁(yè)數(shù)累加到dirty_pages中* */
+ cpu->dirty_pages += count;return count;}
分析kvm_dirty_ring_reap_one函數(shù)的流程:
static uint32_t kvm_dirty_ring_reap_one(KVMState *s, CPUState *cpu)
{/* 取出vcpu上的dirty-ring */struct kvm_dirty_gfn *dirty_gfns = cpu->kvm_dirty_gfns, *cur;/* 取出ring的大小 */uint32_t ring_size = s->kvm_dirty_ring_size;/* 取出本次dirty-ring檢查臟頁(yè)的位置 */uint32_t count = 0, fetch = cpu->kvm_fetch_index;while (true) {/* 由于臟頁(yè)位置是遞增的,需要對(duì)ring的大小取模,獲得其在環(huán)上的位置 */cur = &dirty_gfns[fetch % ring_size];/* 查看對(duì)應(yīng)位置的頁(yè)是否為臟,如果不臟表示沒(méi)有新增的臟頁(yè),中斷循環(huán),如果有繼續(xù) */if (!dirty_gfn_is_dirtied(cur)) {break;}/* 將臟頁(yè)在slot位圖對(duì)應(yīng)位置1 */kvm_dirty_ring_mark_page(s, cur->slot >> 16, cur->slot & 0xffff,cur->offset);dirty_gfn_set_collected(cur);trace_kvm_dirty_ring_page(cpu->cpu_index, fetch, cur->offset);fetch++;/* 統(tǒng)計(jì)新增的臟頁(yè)數(shù) */count++;}cpu->kvm_fetch_index = fetch;/* 將新增的臟頁(yè)數(shù)累加到dirty_pages中 */cpu->dirty_pages += count;return count;
}
速率計(jì)算
開(kāi)始測(cè)量時(shí),獲取vcpu上臟頁(yè)計(jì)數(shù),保存到本地變量 根據(jù)用戶設(shè)置的測(cè)量時(shí)間,睡眠一段時(shí)間 再次獲取vcpu上臟頁(yè)計(jì)數(shù),保存到本地變量 獲取兩次vcpu臟頁(yè)計(jì)數(shù)的增量,得到增加的臟頁(yè)數(shù),計(jì)算增加內(nèi)存總量,得到vcpu的臟頁(yè)速率,累加后得到虛機(jī)臟頁(yè)速率
速率計(jì)算在calculate_dirtyrate_dirty_ring函數(shù)中實(shí)現(xiàn),流程如下:
static void calculate_dirtyrate_dirty_ring(struct DirtyRateConfig config)
{CPUState *cpu;int64_t msec = 0;int64_t start_time;uint64_t dirtyrate = 0;uint64_t dirtyrate_sum = 0;/* 聲明用于保存臟頁(yè)計(jì)數(shù)的本地變量數(shù)組,數(shù)組大小是vcpu的個(gè)數(shù) */DirtyPageRecord *dirty_pages;int nvcpu = 0;int i = 0;/* 獲取虛機(jī)vcpu個(gè)數(shù)*/CPU_FOREACH(cpu) {nvcpu++;}/* 為存放臟頁(yè)計(jì)數(shù)的本地變量數(shù)組分給空間 */dirty_pages = malloc(sizeof(*dirty_pages) * nvcpu);/* 設(shè)置臟頁(yè)統(tǒng)計(jì)信息,因?yàn)榕K頁(yè)速率粒度是vcpu,因此保存的速率有nvcpu個(gè),為其分配空間 */DirtyStat.dirty_ring.nvcpu = nvcpu;DirtyStat.dirty_ring.rates = malloc(sizeof(DirtyRateVcpu) * nvcpu);/* 開(kāi)啟臟頁(yè)日志記錄,開(kāi)始臟頁(yè)速率測(cè)量 */dirtyrate_global_dirty_log_start();/* 遍歷虛機(jī)vcpu上的統(tǒng)計(jì)計(jì)數(shù),將其保存到本地變量數(shù)組dirty_pages中 */CPU_FOREACH(cpu) {record_dirtypages(dirty_pages, cpu, true);}/* 獲取當(dāng)前的測(cè)量時(shí)間 */start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);DirtyStat.start_time = start_time / 1000;/* 睡眠config中指定的測(cè)量時(shí)間 */msec = config.sample_period_seconds * 1000;msec = set_sample_page_period(msec, start_time);DirtyStat.calc_time = msec / 1000;/* 睡眠醒來(lái)后觸發(fā)臟頁(yè)同步,然后停止臟頁(yè)記錄 */dirtyrate_global_dirty_log_stop();/* 遍歷虛機(jī)vcpu上的統(tǒng)計(jì)計(jì)數(shù),將其保存到本地變量數(shù)組dirty_pages中 */CPU_FOREACH(cpu) {record_dirtypages(dirty_pages, cpu, false);}/* * 針對(duì)每個(gè)vcpu,逐一計(jì)算其臟頁(yè)速率,將其存放到全局統(tǒng)計(jì)變量DirtyStat中* 同時(shí)累加vcpu的臟頁(yè)速率,得到整個(gè)虛機(jī)的臟頁(yè)速率* */for (i = 0; i < DirtyStat.dirty_ring.nvcpu; i++) {dirtyrate = do_calculate_dirtyrate_vcpu(dirty_pages[i]);trace_dirtyrate_do_calculate_vcpu(i, dirtyrate);DirtyStat.dirty_ring.rates[i].id = i;DirtyStat.dirty_ring.rates[i].dirty_rate = dirtyrate;dirtyrate_sum += dirtyrate;}/* 將虛機(jī)的臟頁(yè)速率保存到全局統(tǒng)計(jì)變量DirtyStat中 */DirtyStat.dirty_rate = dirtyrate_sum;free(dirty_pages);
}
總結(jié)
以上是生活随笔 為你收集整理的QEMU脏页速率计算原理 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。