kvm內(nèi)存優(yōu)化:
EPT 技術(shù)
? 在虛擬化環(huán)境下,intel開創(chuàng)的硬件輔助內(nèi)存虛擬化技術(shù)。即擴(kuò)展頁表EPT,而AMD也有類似的成為NPT。在此之前,內(nèi)存虛擬化使用的一個重要技術(shù)為影子頁表。(影子頁表采用的是一步到位式,即完成客戶機(jī)虛擬地址GVA到宿主機(jī)物理地址HPA的轉(zhuǎn)換,由VMM為每個客戶機(jī)進(jìn)程維護(hù)。)
? 在虛擬化環(huán)境下,正常訪問內(nèi)存流程:GVA-->GPA-->HPA。
? 有了EPT技術(shù),那么能夠?qū)⑻摂M機(jī)的物理地址直接翻譯為宿主機(jī)的物理地址,從而把后面那個轉(zhuǎn)換過程去掉了,增加了效率。
那么這項(xiàng)技術(shù),現(xiàn)在的服務(wù)器都支持,只要在BIOS打開了intel 的VT設(shè)置,那么這個也一起打開了。
大頁和透明大頁
大頁:指的是內(nèi)存的大頁面。
小頁面:當(dāng)初這個機(jī)制提出的時候,計算機(jī)的內(nèi)存大小也就幾十M,所以當(dāng)時內(nèi)存默認(rèn)的頁面大小都是4KB,那么這個4KB 也就是所謂的小頁面。隨著計算機(jī)的硬件發(fā)展,內(nèi)存基本都是大容量的,操作系統(tǒng)如果還是小頁存在,那么將會產(chǎn)生較多的TLB Miss和缺頁中斷,從而大大影響性能。
? 為什么小頁就存在較多的Miss和缺頁中斷呢?比如說系統(tǒng)里的一個應(yīng)用程序需要2MB的內(nèi)容,如果操作系統(tǒng)還是以4KB小頁為單位,那么內(nèi)存里就要有512個頁面(512*4KB=2M),所以在TLB里就需要512個表項(xiàng)以及512個頁表項(xiàng),因此操作系統(tǒng)就要經(jīng)歷512次的TLB miss和512次的缺頁中斷才能將2MB的應(yīng)用程序空間全部映射到物理內(nèi)存里。想想,2MB內(nèi)存的需要就要經(jīng)歷512次的操作,如果內(nèi)存需求大呢?必然操作數(shù)量會大大增加,從而間接的影響性能。(Translation Lookaside Buffer的縮寫,虛擬尋址的緩存,用于虛擬地址與實(shí)地址之間的交互,提供一個尋找實(shí)地址的緩存區(qū),能夠有效減少尋找物理地址所消耗時間。)
? 如果把這個4KB變成2MB呢?那就很輕松了,一次TLB Miss和缺頁中斷操作就完成了,大大的增加了效率。
? 所以,虛擬機(jī)可以通過分配巨型頁也就是剛才說的大頁來提高運(yùn)行性能。
具體怎么操作呢?
如何把這個4KB的小頁變成2MB甚至1GB的大頁,然后把這個大頁賦給虛擬機(jī)使用?
通過命令 cat /proc/meminfo | grep HugePages 查看當(dāng)前系統(tǒng)有多少個大頁。
運(yùn)行 echo 2000 > /proc/sys/vm/nr_hugepages
永久生效 :sysctl -w vm.nr_hugepages=2000
把大頁進(jìn)行掛載:
mount -t hugetlbfs hugetlbfs /dev/hugepages
這個hugetlbfs 是一種特殊文件系統(tǒng),那至于為什么采用這樣的文件系統(tǒng)是因?yàn)檫@樣花費(fèi)的代價小。
那么通過這幾步操作,開啟->設(shè)置大頁數(shù)量->掛載, 那么宿主機(jī)這塊就沒什么問題了。
如果我們KVM里面的某個虛擬機(jī)要使用宿主機(jī)的大頁,那么我們還得做如下操作:
- 重啟下libvirtd服務(wù);
- 虛擬機(jī)也開啟透明巨型頁;
- 關(guān)閉虛擬機(jī)編輯虛擬機(jī)XML設(shè)置虛擬機(jī)可以使用宿主機(jī)的巨型頁數(shù)量
libvirtd服務(wù)重啟:systemctl restart libvirtd.service;
編輯虛擬機(jī)XML文件,讓它使用宿主機(jī)的大頁,使用virsh edit vmname 命令修改;
在宿主機(jī)運(yùn)行 cat /proc/meminfo | grep -i HugePages 查看下大頁的使用情況;
? 注意這個虛擬機(jī)的內(nèi)存是2G的配置,發(fā)現(xiàn)hugepages_free已經(jīng)變成了912個了,那么使用了2000-912=1088 個;那么2*1088=2176M 正好跟虛擬機(jī)內(nèi)存的大小2G差不多。
那么要讓大頁同時讓多個虛擬機(jī)享用,有以下兩步要做:
給NUMA 各個node節(jié)點(diǎn)分配多個2MB或者1GB的大頁;
-
編輯虛擬機(jī)xml文件以使用node里分配好的大頁。
給宿主機(jī)各個NUMA Node分配大頁:
#echo 4 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages
#echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
這兩個命令的意思就是先給node0里分配4個1GB的大頁,然后再給node1分配1024個2MB的大頁。
然后執(zhí)行相關(guān)掛載操作,這跟剛才我們做的操作類似:
# mkdir /dev/hugepages1G
# mount -t hugetlbfs -o pagesize=1G none /dev/hugepages1G
# mkdir /dev/hugepages2M
# mount -t hugetlbfs -o pagesize=2M none /dev/hugepages2M
掛載成功后,重啟下libvirtd服務(wù),然后虛擬機(jī)就可以使用了,但是這里要注意的是,1GB的大頁,虛擬機(jī)是不能直接使用的,需要在XML里指定。
那么怎么指定? 我們目前宿主機(jī)NUMA node1和node2里面分別有4個1GB的和1024個2MB的大頁。因此,只要跑在這兩node上的虛擬機(jī)都可以享用了。
比如剛才我們那虛擬機(jī),我們要讓它使用1GB的大頁,我們只需要在XML里這樣定義
<memoryBacking>
<hugepages/>
<page size="1" unit="G" nodeset="0-3,5"/>
<page size="2" unit="M" nodeset="4"/>
</hugepages>
</memoryBacking>
紅色的部分就是要添加的參數(shù),size是1,表示第一個使用的page;然后單位unit是G,nodeset="0-3,5" 意思是虛擬機(jī)的NUMA node0,node1, node2 , node3和node5將使用1GB的大頁 ; 虛擬機(jī)的node4將用2MB的大頁。
注意,這里的nodeset指的是虛擬機(jī)的節(jié)點(diǎn),同時還要注意的是,如果宿主機(jī)大頁面不夠用了,你這樣配置了,虛擬機(jī)是會起不來的。
以上就是給虛擬機(jī)分配大頁的方法。當(dāng)然如果你想把宿主機(jī)的大頁關(guān)閉,只要執(zhí)行:
# sysctl vm.nr_hugepages=0
# umount hugetlbfs
透明大頁:
? 從Centos6開始,linux系統(tǒng)自帶了一技術(shù)叫透明巨型頁(transparent huge page),它允許所有的空余內(nèi)存被用作緩存以提高性能,而且這個設(shè)置是默認(rèn)開啟的。
cat /sys/kernel/mm/transparent_hugepage/enabled 可以查看。
我們看到這個中括號把這個always括起來了,說明這機(jī)器的透明巨型頁的功能是打開的。當(dāng)有512個頁面可以整合的時候,就會合成一個2MB的大頁;
如果是在括號把never括起來了,那么就是關(guān)閉狀態(tài);
madvise的話就是避免改變內(nèi)存占用。
下面命令是關(guān)閉巨型頁:
echo never >/sys/kernel/mm/transparent_hugepage/enabled
最后要注意的是透明巨型頁跟剛才我們說的hugetlbfs 文件掛載大頁是不沖突的,如果你沒做任何大頁的指定和掛載,那么KVM就會使用透明大頁的方式。
那么說到這,大家就會疑問,既然有透明大頁,我為何還要費(fèi)勁的去做相關(guān)大頁的指定? 其實(shí)這兩種方式都差不多,區(qū)別就是一個是手動的一,個是自動的。如果你對你宿主機(jī)資源把握的更加精準(zhǔn),推薦的還是手動指定。
KSM 技術(shù)
? KSM(Kernel SamePage Merging),也就是所謂的相同頁面內(nèi)存壓縮技術(shù)。
KSM服務(wù)在linux系統(tǒng)里默認(rèn)是開啟的,它的作用就是讓內(nèi)存利用的更加高效,如果多個程序中用的內(nèi)存都是相同的頁面,那么KSM就會把相同的內(nèi)存合并,這樣就能騰出更多的空間。
KSM在系統(tǒng)里有個守護(hù)進(jìn)程,它的作用就是不斷的掃描宿主機(jī)的內(nèi)存情況,檢測有相同的頁面就會合并,當(dāng)然這或多或少會消耗點(diǎn)CPU。
? 如果你的環(huán)境,內(nèi)存資源比較豐富,建議這個功能開不開啟都無所謂;如果不夠,又想跑多一點(diǎn)的虛擬機(jī),那么可以打開這個功能,但是你一定要清楚,這個是一種內(nèi)存超用的方案,假如你的大部分虛擬機(jī)內(nèi)存變化比較頻繁(比如內(nèi)存使用率一下高,一下低),那么不建議開啟,因?yàn)閮?nèi)存不夠了,就會用到swap,那么這個會嚴(yán)重影響虛擬機(jī)性能。
首先是開關(guān)KSM服務(wù)
systemctl start|stop ksmd
systemctl start|stop ksmtuned
systemctl enable|disable ksmd
systemctl enable|disable ksmtuned
其次是在宿主機(jī)KSM服務(wù)打開的情況下,如果不想讓虛擬機(jī)受宿主機(jī)KSM的影響,那么可以這么操作:
編輯虛擬機(jī)的XML文件,添加:
<memoryBacking>
<nosharepages/>
</memoryBacking>
這樣,這個KSM就不會去合并這個虛擬機(jī)的內(nèi)存了
總的來說,用不用KSM視你自己的生產(chǎn)環(huán)境具體情況而定。
內(nèi)存限制技術(shù)
通過虛擬機(jī)內(nèi)存限制,可以讓虛擬機(jī)的內(nèi)存使用限制在一定范圍內(nèi)。
? 比如你的一臺KVM宿主機(jī),里面跑著多個業(yè)務(wù)的虛擬機(jī),有的虛擬機(jī)業(yè)務(wù)比較大,吃得內(nèi)存多,有的業(yè)務(wù)比較低,用不了多少內(nèi)存,那么我們可以通過內(nèi)存限制技術(shù)來手動調(diào)節(jié)宿主機(jī)的內(nèi)存分配。
? 使用這個必須對你虛擬化環(huán)境特別清楚,比如宿主機(jī)平時的負(fù)載情況以及各個虛擬機(jī)的負(fù)載情況。
? 通過memtune命令或者通過改虛擬機(jī)的XML文件來設(shè)定內(nèi)存的限制.
hard_limit:強(qiáng)制設(shè)置虛擬機(jī)最大使用內(nèi)存,單位為KB
soft_limit:可用最大內(nèi)存,單位為KB
swap_hard_limit:虛擬機(jī)最多使用的內(nèi)存加上swap的大小,單位為KB
min_guarantee:強(qiáng)制設(shè)置虛擬機(jī)最低使用的內(nèi)存,單位為KB
最后一個參數(shù)雖然OPTIONS里有列出,但是實(shí)測是發(fā)現(xiàn)CentOS7.0 以上系統(tǒng)不能支持,執(zhí)行的時候會報下面這樣的錯誤: ?
還可以通過修改XML的方式來現(xiàn)在虛擬機(jī)的內(nèi)存。
我們在XML里添加下面這個配置即可:
<memtune>
<hard_limit unit='KiB'>9437184</hard_limit>
<soft_limit unit='KiB'>8388608</soft_limit>
<swap_hard_limit unit='KiB'>10485760</swap_hard_limit>
</memtune>
以上幾點(diǎn)就是KVM在內(nèi)存方面的優(yōu)化設(shè)置,大家要根據(jù)自己的生產(chǎn)環(huán)境情況,去做相關(guān)的調(diào)試.