天天看點

調整linux記憶體分頁大小,JVM優化調整大記憶體分頁(Large Page)

記憶體分頁大小對性能調優的原理

首先,我們需要先回顧一下計算機組成原理,這是了解大記憶體分頁的對JVM性能調優的前提。

什麼是記憶體分頁?

我們知道,CPU通過尋址來通路記憶體。我們以32位CPU尋址為例。

調整linux記憶體分頁大小,JVM優化調整大記憶體分頁(Large Page)

資料總線:主要用來傳輸資料,高電平,低電平分别表示0和1

位址總線:主要控制對記憶體條的哪塊記憶體進行操作(尋址),32位共32根線,每根有兩種狀态分别表示0,或者1。共2^32。2^30為1G,是以共4G。

控制總線:主要控制是讀還是寫。

也就是說最大可以支援的實體記憶體是4G,但是在實際之中,程式可能需要4G但是記憶體小于4G,導緻程式不可用或者降低程式占用記憶體。

為了解決此類問題,現代CPU引入了Memory Management

Unit記憶體管理單元)。

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

記憶體分頁(Paging)是在使用MMU的基礎上,提出的一種記憶體管理機制。它将虛拟位址和實體位址按固定大小(4K)分割成頁(page)和頁幀(page

frame),并保證頁與頁幀的大小相同。

這種機制,從OS能支援非連續性的記憶體配置設定。在程式記憶體不夠用時,還可以将不常用的實體記憶體頁轉移到其他儲存設備上,比如磁盤,這就是大家耳熟能詳的虛拟記憶體。

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

調整linux記憶體分頁大小,JVM優化調整大記憶體分頁(Large Page)

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

進一步優化,引入TLB(Translation lookaside

buffer,頁表寄存器緩沖)由上一節可知,頁表是被存儲在記憶體中的。我們知道CPU通過總線通路記憶體,肯定慢于直接通路寄存器的。為了進一步優化性能,現代CPU架構引入了,用來緩存一部分經常通路的頁表内容。

調整linux記憶體分頁大小,JVM優化調整大記憶體分頁(Large Page)

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

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

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

調整OS和JVM記憶體分頁

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

Linux:限制:需要2.6核心以上或2.4核心已打大記憶體頁更新檔。确認是否支援,請在終端敲如下指令:

# cat /proc/meminfo | grep

Huge

HugePages_Total: 0

HugePages_Free: 0

Hugepagesize: 2048 kB

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

共享記憶體段最大值建議這個值大于JavaHeap

size,這個例子裡設定了4G記憶體。

# echo 4294967295 >

/proc/sys/kernel/shmmax

大記憶體頁數量

# echo 154 >

/proc/sys/vm/nr_hugepages

這個值一般是程序占用最大記憶體/單個頁的大小 ,比如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.

重新開機電腦

注意: 需要管理者操作。

單個頁大小調整JVM啟用時加參數

-XX:LargePageSizeInBytes=10m如果JDK是在1.5 update5以前的,還需要手動加 -XX:+UseLargePages,作用是啟用大記憶體頁支援。

大記憶體分頁的副作用

因為每頁size變大了,導緻JVM在計算Heap内部分區(perm,

new,

old)記憶體占用比例時,會出現超出正常值的劃分。最壞情況下是,某個區會多占用一個頁的大小。不過後續jvm版本也在調整這個政策。

一般情況,不建議将頁size調得太大,4-64M,是可以接受的(預設是4M)。為了合理設定這個值,你應該對你的系統做一下benchmark。說實話,網上我見過調得最猛的,有調到256M,從benchmark報表上看,性能不是太壞。如果你有64位的大記憶體機器,不妨嘗試一下。

另外,網上有很多GC調優的文章内容中都有提到 LargePageSizeInBytes,但未提任何OS限制。在OS不支援的情況下,設定這個參數,這個參數将僅僅是個擺設。