linux之hugepage
?
參考o(jì)racle 數(shù)據(jù)庫(kù)官網(wǎng)提到的關(guān)于hugepage的介紹,上面提到:
HugePages is a feature integrated into the Linux kernel 2.6. Enabling HugePages makes it possible for the operating system to support memory pages greater than the default (usually 4 KB). Using very large page sizes can improve system performance by reducing the amount of system resources required to access page table entries. HugePages is useful for both 32-bit and 64-bit configurations. HugePage sizes vary from 2 MB to 256 MB, depending on the kernel version and the hardware architecture. For Oracle Databases, using HugePages reduces the operating system maintenance of page states, and increases Translation Lookaside Buffer (TLB) hit ratio.
翻譯一下就是:
HugePages是集成到Linux內(nèi)核2.6中的一個(gè)特性。啟用HugePages使得操作系統(tǒng)能夠支持大于默認(rèn)值(通常為4 KB)的內(nèi)存分頁(yè)。使用非常大的頁(yè)面大小可以減少訪問(wèn)頁(yè)表項(xiàng)所需的系統(tǒng)資源,從而提高系統(tǒng)性能。HugePages對(duì)于32位和64位配置都很有用。大頁(yè)面大小從2 MB到256 MB不等,具體取決于內(nèi)核版本和硬件架構(gòu)。對(duì)于Oracle數(shù)據(jù)庫(kù),使用HugePages可以減少操作系統(tǒng)對(duì)頁(yè)面狀態(tài)的維護(hù),并提高Translation Lookaside Buffer(旁路轉(zhuǎn)換緩沖,或稱(chēng)為頁(yè)表緩沖,即TLB。關(guān)于TLB的介紹可參考。)的命中率。
本文參考:
https://juejin.cn/post/6844903507594575886
https://zhuanlan.zhihu.com/p/65298260
原文寫(xiě)的非常好,此篇做筆記用。
?
?
介紹Hugepage首先需要知道什么是虛擬內(nèi)存。
虛擬內(nèi)存
我們知道一個(gè)進(jìn)程是與其他進(jìn)程共享CPU和內(nèi)存資源的。為了防止進(jìn)程之間內(nèi)存泄漏的問(wèn)題,現(xiàn)代操作系統(tǒng)提供了一種對(duì)主存的抽象概念,即是虛擬內(nèi)存(Virtual Memory)。虛擬內(nèi)存為每個(gè)進(jìn)程提供了一個(gè)一致的、私有的地址空間,它讓每個(gè)進(jìn)程產(chǎn)生了一種自己在獨(dú)享主存的錯(cuò)覺(jué)(每個(gè)進(jìn)程擁有一片連續(xù)完整的內(nèi)存空間)。
因?yàn)槭褂锰摂M地址可以帶來(lái)諸多好處:
既然使用虛擬地址,就涉及到將虛擬地址轉(zhuǎn)換為物理地址的過(guò)程,也即CPU尋址。
CPU尋址
內(nèi)存通常被組織為一個(gè)由M個(gè)連續(xù)的字節(jié)大小的單元組成的數(shù)組,每個(gè)字節(jié)都有一個(gè)唯一的物理地址(Physical Address PA),作為到數(shù)組的索引。CPU訪問(wèn)內(nèi)存最簡(jiǎn)單直接的方法就是使用物理地址,這種尋址方式被稱(chēng)為物理尋址。
現(xiàn)代處理器使用的是一種稱(chēng)為虛擬尋址(Virtual Addressing)的尋址方式。使用虛擬尋址,CPU需要將虛擬地址翻譯成物理地址,這樣才能訪問(wèn)到真實(shí)的物理內(nèi)存。它需要MMU(Memory Management Unit)和頁(yè)表(page table)的共同參與。
MMU
MMU是處理器/核(processer)中的一個(gè)硬件單元,通常每個(gè)核有一個(gè)MMU。它的功能是將虛擬地址轉(zhuǎn)換為物理地址。MMU需要借助存放在內(nèi)存中的頁(yè)表(page table)來(lái)動(dòng)態(tài)翻譯虛擬地址,該頁(yè)表由操作系統(tǒng)管理。
MMU由兩部分組成:TLB(Translation Lookaside Buffer)和table walk unit。
Page Table
page table是每個(gè)進(jìn)程獨(dú)有的,是軟件實(shí)現(xiàn)的,是存儲(chǔ)在main memory(比如DDR)中的。所謂頁(yè)表就是一個(gè)存放在物理內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),它記錄了虛擬頁(yè)與物理頁(yè)的映射關(guān)系。
頁(yè)表是一個(gè)元素為頁(yè)表?xiàng)l目(Page Table Entry, PTE)的集合,每個(gè)虛擬頁(yè)在頁(yè)表中一個(gè)固定偏移量的位置上都有一個(gè)PTE。下面是PTE僅含有一個(gè)有效位標(biāo)記的頁(yè)表結(jié)構(gòu),該有效位代表這個(gè)虛擬頁(yè)是否被緩存在物理內(nèi)存中。
虛擬頁(yè)VP 0、VP 4、VP 6、VP 7被緩存在物理內(nèi)存中,虛擬頁(yè)VP 2和VP 5被分配在頁(yè)表中,但并沒(méi)有緩存在物理內(nèi)存,虛擬頁(yè)VP 1和VP 3還沒(méi)有被分配。
在進(jìn)行動(dòng)態(tài)內(nèi)存分配時(shí),例如malloc()函數(shù)或者其他高級(jí)語(yǔ)言中的new關(guān)鍵字,操作系統(tǒng)會(huì)在硬盤(pán)中創(chuàng)建或申請(qǐng)一段虛擬內(nèi)存空間,并更新到頁(yè)表(分配一個(gè)PTE,使該P(yáng)TE指向硬盤(pán)上這個(gè)新創(chuàng)建的虛擬頁(yè))。
頁(yè)命中
如下圖所示,MMU根據(jù)虛擬地址在頁(yè)表中尋址到了PTE 4,該P(yáng)TE的有效位為1,代表該虛擬頁(yè)已經(jīng)被緩存在物理內(nèi)存中了,最終MMU得到了PTE中的物理內(nèi)存地址(指向PP 1)。
缺頁(yè)
如下圖所示,MMU根據(jù)虛擬地址在頁(yè)表中尋址到了PTE 2,該P(yáng)TE的有效位為0,代表該虛擬頁(yè)并沒(méi)有被緩存在物理內(nèi)存中。虛擬頁(yè)沒(méi)有被緩存在物理內(nèi)存中(緩存未命中)被稱(chēng)為缺頁(yè)。
當(dāng)CPU遇見(jiàn)缺頁(yè)時(shí)會(huì)觸發(fā)一個(gè)缺頁(yè)異常,缺頁(yè)異常將控制權(quán)轉(zhuǎn)向操作系統(tǒng)內(nèi)核,然后調(diào)用內(nèi)核中的缺頁(yè)異常處理程序,該程序會(huì)選擇一個(gè)犧牲頁(yè),如果犧牲頁(yè)已被修改過(guò),內(nèi)核會(huì)先將它復(fù)制回硬盤(pán)(采用寫(xiě)回機(jī)制而不是直寫(xiě)也是為了盡量減少對(duì)硬盤(pán)的訪問(wèn)次數(shù)),然后再把該虛擬頁(yè)覆蓋到犧牲頁(yè)的位置,并且更新PTE。
當(dāng)缺頁(yè)異常處理程序返回時(shí),它會(huì)重新啟動(dòng)導(dǎo)致缺頁(yè)的指令,該指令會(huì)把導(dǎo)致缺頁(yè)的虛擬地址重新發(fā)送給MMU。由于現(xiàn)在已經(jīng)成功處理了缺頁(yè)異常,所以最終結(jié)果是頁(yè)命中,并得到物理地址。
這種在硬盤(pán)和內(nèi)存之間傳送頁(yè)的行為稱(chēng)為頁(yè)面調(diào)度(paging):頁(yè)從硬盤(pán)換入內(nèi)存和從內(nèi)存換出到硬盤(pán)。當(dāng)缺頁(yè)異常發(fā)生時(shí),才將頁(yè)面換入到內(nèi)存的策略稱(chēng)為按需頁(yè)面調(diào)度(demand paging),所有現(xiàn)代操作系統(tǒng)基本都使用的是按需頁(yè)面調(diào)度的策略。
虛擬內(nèi)存跟CPU高速緩存(或其他使用緩存的技術(shù))一樣依賴(lài)于局部性原則。雖然處理缺頁(yè)消耗的性能很多(畢竟還是要從硬盤(pán)中讀取),而且程序在運(yùn)行過(guò)程中引用的不同虛擬頁(yè)的總數(shù)可能會(huì)超出物理內(nèi)存的大小,但是局部性原則保證了在任意時(shí)刻,程序?qū)②呄蛴谠谝粋€(gè)較小的活動(dòng)頁(yè)面(active page)集合上工作,這個(gè)集合被稱(chēng)為工作集(working set)。根據(jù)空間局部性原則(一個(gè)被訪問(wèn)過(guò)的內(nèi)存地址以及其周邊的內(nèi)存地址都會(huì)有很大幾率被再次訪問(wèn))與時(shí)間局部性原則(一個(gè)被訪問(wèn)過(guò)的內(nèi)存地址在之后會(huì)有很大幾率被再次訪問(wèn)),只要將工作集緩存在物理內(nèi)存中,接下來(lái)的地址翻譯請(qǐng)求很大幾率都在其中,從而減少了額外的硬盤(pán)流量。
如果一個(gè)程序沒(méi)有良好的局部性,將會(huì)使工作集的大小不斷膨脹,直至超過(guò)物理內(nèi)存的大小,這時(shí)程序會(huì)產(chǎn)生一種叫做抖動(dòng)(thrashing)的狀態(tài),頁(yè)面會(huì)不斷地?fù)Q入換出,如此多次的讀寫(xiě)硬盤(pán)開(kāi)銷(xiāo),性能自然會(huì)十分“恐怖”。所以,想要編寫(xiě)出性能高效的程序,首先要保證程序的時(shí)間局部性與空間局部性。
多級(jí)頁(yè)表
上面討論的只是單頁(yè)表,但在實(shí)際的環(huán)境中虛擬空間地址都是很大的(一個(gè)32位系統(tǒng)的地址空間有2^32 = 4GB,更別說(shuō)64位系統(tǒng)了)。在這種情況下,使用一個(gè)單頁(yè)表明顯是效率低下的,而且非常占內(nèi)存空間。
常用方法是使用層次結(jié)構(gòu)的頁(yè)表。
假設(shè)我們的環(huán)境為一個(gè)32位的虛擬地址空間,它有如下形式:
-
虛擬地址空間被分為4KB的頁(yè),每個(gè)PTE都是4字節(jié)。
-
內(nèi)存的前2K個(gè)頁(yè)面分配給了代碼和數(shù)據(jù)。
-
之后的6K個(gè)頁(yè)面還未被分配。
-
再接下來(lái)的1023個(gè)頁(yè)面也未分配,其后的1個(gè)頁(yè)面分配給了用戶(hù)棧。
下圖是為該虛擬地址空間構(gòu)造的二級(jí)頁(yè)表層次結(jié)構(gòu)(真實(shí)情況中多為四級(jí)或更多),一級(jí)頁(yè)表(1024個(gè)PTE正好覆蓋4GB的虛擬地址空間,同時(shí)每個(gè)PTE只有4字節(jié),這樣一級(jí)頁(yè)表與二級(jí)頁(yè)表的大小也正好與一個(gè)頁(yè)面的大小一致都為4KB)的每個(gè)PTE負(fù)責(zé)映射虛擬地址空間中一個(gè)4MB的片(chunk),每一片都由1024個(gè)連續(xù)的頁(yè)面組成。二級(jí)頁(yè)表中的每個(gè)PTE負(fù)責(zé)映射一個(gè)4KB的虛擬內(nèi)存頁(yè)面。
這個(gè)結(jié)構(gòu)看起來(lái)很像是一個(gè)B-Tree,這種層次結(jié)構(gòu)有效的減緩了內(nèi)存要求:
-
如果一個(gè)一級(jí)頁(yè)表的一個(gè)PTE是空的,那么相應(yīng)的二級(jí)頁(yè)表也不會(huì)存在。這代表一種巨大的潛在節(jié)約(對(duì)于一個(gè)普通的程序來(lái)說(shuō),虛擬地址空間的大部分都會(huì)是未分配的)。
-
只有一級(jí)頁(yè)表才總是需要緩存在內(nèi)存中的,這樣虛擬內(nèi)存系統(tǒng)就可以在需要時(shí)創(chuàng)建、頁(yè)面調(diào)入或調(diào)出二級(jí)頁(yè)表(只有經(jīng)常使用的二級(jí)頁(yè)表才會(huì)被緩存在內(nèi)存中),這就減少了內(nèi)存的壓力。
TLB
表是被緩存在內(nèi)存中的,盡管內(nèi)存的速度相對(duì)于硬盤(pán)來(lái)說(shuō)已經(jīng)非常快了,但與CPU還是有所差距。為了防止每次地址翻譯操作都需要去訪問(wèn)內(nèi)存,CPU使用了高速緩存與TLB來(lái)緩存PTE。CPU會(huì)首先在TLB中查找,因?yàn)樵赥LB中找起來(lái)很快。TLB之所以快,一是因?yàn)樗械膃ntries的數(shù)目較少,二是TLB是集成進(jìn)CPU的,它幾乎可以按照CPU的速度運(yùn)行。
TLB(Translation Lookaside Buffer, TLB)旁路緩沖器,或叫做頁(yè)表緩存,它是MMU中的一個(gè)緩沖區(qū)。
TLB命中:
-
第一步,CPU將一個(gè)虛擬地址交給MMU進(jìn)行地址翻譯。
-
第二步和第三步,MMU通過(guò)TLB取得相應(yīng)的PTE。
-
第四步,MMU通過(guò)PTE翻譯出物理地址并將它發(fā)送給高速緩存/內(nèi)存。
-
第五步,高速緩存返回?cái)?shù)據(jù)到CPU(如果緩存命中的話,否則還需要訪問(wèn)內(nèi)存)。
TLB未命中:
當(dāng)TLB未命中時(shí),MMU必須從高速緩存/內(nèi)存中取出相應(yīng)的PTE,并將新取得的PTE存放到TLB(如果TLB已滿(mǎn)會(huì)覆蓋一個(gè)已經(jīng)存在的PTE)。如下圖:
綜上,整個(gè)cpu尋址的過(guò)程可以用下圖表示:
?
如果在TLB中找到了含有該虛擬地址的entry(TLB hit),則可從該entry【1】中直接獲取對(duì)應(yīng)的物理地址,否則就不幸地TLB miss了,就得去查找當(dāng)前進(jìn)程的page table。這個(gè)時(shí)候,組成MMU的另一個(gè)部分table walk unit就被召喚出來(lái)了,這里面的table就是page table。
如果在page table中找到了該虛擬地址對(duì)應(yīng)的entry的p(present)位是1,說(shuō)明該虛擬地址對(duì)應(yīng)的物理頁(yè)面當(dāng)前駐留在內(nèi)存中,也就是page table hit。找到了還沒(méi)完,接下來(lái)還有兩件事要做:
如果該虛擬地址對(duì)應(yīng)的entry的p位是0,就會(huì)觸發(fā)page fault(缺頁(yè)中斷),可能有這幾種情況:
如果這個(gè)虛擬地址在進(jìn)程的page table中根本不存在,說(shuō)明這個(gè)虛擬地址不在該進(jìn)程的地址空間中,這時(shí)也會(huì)觸發(fā)segmantation fault。
HugePage
上面中提到使用多級(jí)頁(yè)表的方式對(duì)于減少頁(yè)表自身占用的內(nèi)存空間確實(shí)是非常有效的。然而,為此付出的代價(jià)就是增加了地址轉(zhuǎn)換過(guò)程中對(duì)內(nèi)存的訪問(wèn)次數(shù),進(jìn)而增加了轉(zhuǎn)換時(shí)間。那在除了前面介紹的TLB之外,還有哪些可以減少內(nèi)存訪問(wèn)次數(shù),加快地址轉(zhuǎn)換的方法呢?HugePage即可以。
而HugePage它是使用較大的內(nèi)存頁(yè)來(lái)代替默認(rèn)的4k大小,這就意味相同的物理內(nèi)存,內(nèi)存頁(yè)的數(shù)量會(huì)更少,所以需要的page table(頁(yè)表?xiàng)l目也會(huì)變少),同樣TLB的條目數(shù)也會(huì)變少。
好處是:
節(jié)約了頁(yè)表所占用的內(nèi)存大小,并且地址轉(zhuǎn)換變少。所以缺頁(yè)中斷變少,TLBmiss變少。從而提高了內(nèi)存訪問(wèn)性能、TLB命中率,從整體上提高了系統(tǒng)的效率 。
另外,由于地址轉(zhuǎn)換所需的信息一般保存在CPU的緩存中,huge page的使用讓地址轉(zhuǎn)換信息減少,從而減少了CPU緩存的使用,減輕了CPU緩存的壓力,讓CPU緩存能更多地用于應(yīng)用程序的數(shù)據(jù)緩存,也能夠在整體上提升系統(tǒng)的性能。
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的linux之hugepage的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 简单好用的安卓程序开发平台E4A
- 下一篇: IPGUARD Linux系统客户端安装