1. 程式人生 > 其它 >旁路模式,numa、mmu、調整記憶體分頁大小

旁路模式,numa、mmu、調整記憶體分頁大小

bypass

bypass,就是可以通過特定的觸發狀態(斷電或宕機)讓兩個網路不通過網路安全裝置的系統,而直接物理上導通,所以有了Bypass後,當網路安全裝置故障以後,還可以讓連線在這臺裝置上的網路相互導通,當然這個時候這臺網絡裝置也就不會再對網路中的封包做處理了。

ByPass Mode略過模式旁路模式),泛指在一個系統的正常流程中,有一堆檢核機制,而“ByPass Mode”就是當檢核機制發生異常,無法在短期間內排除時,使系統作業能繞過這些檢核機制,使系統能夠繼續執行的作業模式。

 

 

numa

numa是一種關於多個cpu如何訪問記憶體的架構模型,現在的cpu基本都是numa架構,linux核心2.5開始支援numa。

numa架構簡單點兒說就是,一個物理cpu(一般包含多個邏輯cpu或者說多個核心)構成一個node,這個node不僅包括cpu,還包括一組記憶體插槽,也就是說一個物理cpu以及一塊記憶體構成了一個node。每個cpu可以訪問自己node下的記憶體,也可以訪問其他node的記憶體,但是訪問速度是不一樣的,自己node下的更快。

numactl --hardware命令可以檢視node狀況。

通過numactl啟動程式,可以指定node繫結規則和記憶體使用規則。可以通過cpunodebind引數使程序使用固定node上的cpu,使用localalloc引數指定程序只使用cpu所在node上分配的記憶體。如果分配的node上的記憶體足夠用,這樣可以減少抖動,提供效能。如果記憶體緊張,則應該使用interleave引數,否則程序會因為只能使用部分記憶體而out of memory或者使用swap區造成效能下降。

NUMA的記憶體分配策略有localalloc、preferred、membind、interleave。

  • localalloc規定程序從當前node上請求分配記憶體;
  • preferred比較寬鬆地指定了一個推薦的node來獲取記憶體,如果被推薦的node上沒有足夠記憶體,程序可以嘗試別的node。
  • membind可以指定若干個node,程序只能從這些指定的node上請求分配記憶體。
  • interleave規定程序從指定的若干個node上以RR(Round Robin 輪詢排程)演算法交織地請求分配記憶體。

  

 

大頁記憶體

我們知道,CPU是通過定址來訪問記憶體的。32位CPU的定址寬度是 0~0xFFFFFFFF ,16^8 計算後得到的大小是4G,也就是說可支援的實體記憶體最大是4G。

但在實踐過程中,碰到了這樣的問題,程式需要使用4G記憶體,而可用實體記憶體小於4G,導致程式不得不降低記憶體佔用。
為了解決此類問題,現代CPU引入了 MMU(Memory Management Unit 記憶體管理單元)。

MMU 的核心思想是利用虛擬地址替代實體地址,即CPU定址時使用虛址,由 MMU 負責將虛址對映為實體地址。
MMU的引入,解決了對實體記憶體的限制,對程式來說,就像自己在使用4G記憶體一樣。

程序執行緒mmu
https://www.zhihu.com/zvideo/1469706912229429248

 

記憶體分頁(Paging)是在使用MMU的基礎上,提出的一種記憶體管理機制。它將虛擬地址和實體地址按固定大小(4K)分割成頁(page)和頁幀(page frame),並保證頁與頁幀的大小相同。

這種機制,從資料結構上,保證了訪問記憶體的高效,並使OS能支援非連續性的記憶體分配。
在程式記憶體不夠用時,還可以將不常用的實體記憶體頁轉移到其他儲存裝置上,比如磁碟,這就是大家耳熟能詳的虛擬記憶體swap。

在上文中提到,虛擬地址與實體地址需要通過對映,才能使CPU正常工作。
而對映就需要儲存對映表。在現代CPU架構中,對映關係通常被儲存在實體記憶體上一個被稱之為頁表(page table)的地方。
如下圖:

 

 

從這張圖中,可以清晰地看到CPU與頁表,實體記憶體之間的互動關係。

進一步優化,引入TLB(Translation lookaside buffer,頁表暫存器緩衝)
由上一節可知,頁表是被儲存在記憶體中的。我們知道CPU通過匯流排訪問記憶體,肯定慢於直接訪問暫存器的。
為了進一步優化效能,現代CPU架構引入了TLB,用來快取一部分經常訪問的頁表內容。
如下圖:

 

 

對比前面那張圖,在中間加入了TLB。

為什麼要支援大記憶體分頁?
TLB是有限的,這點毫無疑問。當超出TLB的儲存極限時,就會發生 TLB miss,之後,OS就會命令CPU去訪問記憶體上的頁表。如果頻繁的出現TLB miss,程式的效能會下降地很快。

為了讓TLB可以儲存更多的頁地址對映關係,我們的做法是調大記憶體分頁大小。

如果一個頁4M,對比一個頁4K,前者可以讓TLB多儲存1000個頁地址對映關係,效能的提升是比較可觀的。

調整OS記憶體分頁

Linux和windows下要啟用大記憶體頁,有一些限制和設定步驟。

Linux:
限制:需要2.6核心以上或2.4核心已打大記憶體頁補丁。
確認是否支援,請在終端敲如下命令:

# cat /proc/meminfo | grep Huge
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 2048 kB # hugepagesize設定見文件:https://www.jianshu.com/p/b9470fc331dd

如果有HugePage字樣的輸出內容,說明你的OS是支援大記憶體分頁的。Hugepagesize就是預設的大記憶體頁size。
接下來,為了讓JVM可以調整大記憶體頁size,需要設定下OS 共享記憶體段最大值 和 大記憶體頁數量。

共享記憶體段最大值
建議這個值大於Java Heap size,這個例子裡設定了4G記憶體。

# echo 4294967295 > /proc/sys/kernel/shmmax

大記憶體頁數量

# echo 154 > /proc/sys/vm/nr_hugepages

這個值一般是 Java程序佔用最大記憶體/單個頁的大小 ,比如java設定 1.5G,單個頁 10M,那麼數量為  1536/10 = 154。
注意:因為proc是記憶體FS,為了不讓你的設定在重啟後被沖掉,建議寫個指令碼放到 init 階段(rc.local)。

Windows:
限制:僅支援 windows server 2003 以上server版本
操作步驟:

  1. Control Panel -> Administrative Tools -> Local Security Policy
  2. Local Policies -> User Rights Assignment
  3. 雙擊 “Lock pages in memory”, 新增使用者和組
  4. 重啟電腦

注意: 需要管理員操作。