日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

QEMU脏页速率计算原理

發(fā)布時(shí)間:2023/12/20 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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ì)算

  • 速率計(jì)算比較簡(jiǎn)單,步驟如下:
  • 開(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ì)算

    • dirty-ring速率計(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ò),歡迎將生活随笔推薦給好友。