使用HugePages最佳化記憶體效能
著作權聲明:轉載時請以超連結形式標明文章原始出處和作者資訊及本聲明
http://blog.csdn.net/wenshuangzhu/article/details/44095565
1. 引子
系統進程是通過虛擬位址訪問記憶體,但是CPU必須把它轉換程實體記憶體地址才能真正訪問記憶體。為了提高這個轉換效率,CPU會緩衝最近的虛擬記憶體地址和實體記憶體地址的映射關係,並儲存在一個由CPU維護的映射表中。為了盡量提高記憶體的訪問速度,需要在映射表中儲存盡量多的映射關係。
而在Linux中,記憶體都是以頁的形式劃分的,預設情況下每頁是4K,這就意味著如果實體記憶體很大,則映射表的條目將會非常多,會影響CPU的檢索效率。因為記憶體大小是固定的,為了減少映射表的條目,可採取的辦法只有增加頁的尺寸。
2. HugePages簡介 2.1 相關概念
HugePages是在Linux2.6核心被引入的,主要提供4k的page和比較大的page的選擇。
概念 |
概念說明 |
page table |
page table是作業系統上的虛擬記憶體系統的資料結構模型,用於儲存虛擬位址與物理地址的對應關係。 當我們訪問記憶體時,首先訪問page table,然後Linux在通過page table的mapping來訪問真實實體記憶體(ram+swap) |
TLB |
A Translation Lookaside Buffer (TLB) TLB是在cpu中分配的一個固定大小的buffer(or cache),用於儲存page table的部分內容,使CPU更快的訪問並進行地址轉換。 |
hugetlb |
hugetlb 是記錄在TLB 中的條目並指向Hugepages。 |
hugetlbfs |
這是一個新的基於2.6 kernel之上的記憶體檔案系統,如同tmpfs。 在TLB中通過hugetlb來指向hugepage。這些被分配的hugepage作為記憶體檔案系統hugetlbfs(類似tmpfs)提供給進程使用。 |
2.2 使用HugePages的意義
HugePages是Linux核心的一個特性,使用hugepage可以用更大的記憶體頁來取代傳統的4K頁面。使用HugePage主要帶來以下好處:
1. HugePages 會在系統啟動時,直接分配並保留對應大小的記憶體地區。
2. HugePages 在開機之後,如果沒有管理員的介入,是不會釋放和改變的。
3. 沒有swap。
Notswappable: HugePages are not swappable. Therefore thereis no page-in/page-outmechanism overhead.HugePages are universally regarded aspinned.
4. 大大提高了CPU cache中存放的page table所覆蓋的記憶體大小,從而提高了TLB命中率。
進程的虛擬記憶體位址區段先串連到page table然後再串連到實體記憶體。所以在訪問記憶體時需要先訪問page tables得到虛擬記憶體和實體記憶體的映射關係,然後再訪問實體記憶體。
CPU cache中有一部分TLB用來存放部分page table以提高這種轉換的速度。因為page size變大了,所以同樣大小的TLB,所覆蓋的記憶體大小也變大了。提高了TLB命中率,也提高了地址轉換的速度。
5. 減輕page table的負載。
進行XXX系統效能測試時,如果沒有使用HugePages,資料庫伺服器上的pagetable大小大約為5G(這應該也是導致效能測試時資料庫伺服器記憶體不足的主要原因):
node74:/home/Oracle # cat /proc/meminfo
MemTotal: 16323732 kB
PageTables: 5442384kB
配置了HugePages後,pagetable大小僅為124M(效能測試時記憶體使用量率穩定在80%左右):
node74:/home/oracle # cat /proc/meminfo
MemTotal: 16323732 kB
PageTables: 127384 kB
Eliminated page tablelookup overhead: 因為hugepage是不swappable的,所有就沒有page table lookups。
Faster overall memory performance: 由於虛擬記憶體需要兩步操作才能實際對應到實體記憶體地址,因此更少的pages,減輕了page table訪問熱度,避免了page table熱點瓶頸問題。
6. 提高記憶體的效能,降低CPU負載,原理同上
2.3 使用HugePages需要注意的地方
1. Hugepages是在分配後就會預留出來的,其大小一定要比伺服器上所有執行個體的SGA總和要大,差一點都不行。
比如說Hugepages設定為8G,oracle SGA為9G,那麼oracle在啟動的時候就不會使用到這8G的Hugepages。這8G就浪費了。所以在設定Hugepages時要計算SGA的大小,後面會給出一個指令碼來計算。
2. 其他進程無法使用Hugepages的記憶體,所以不要設定太大,稍稍比SGA大一點保證SGA可以使用到hugepages就好了。
3. 在meminfo中和Hugepage相關的有四項:
HugePages_Total: 4611
HugePages_Free: 474
HugePages_Rsvd: 467
Hugepagesize: 2048 kB
HugePages_Total為所分配的頁面數目,和Hugepagesize相乘後得到所分配的記憶體大小。4611*2/1024大約為9GB
HugePages_Free為從來沒有被使用過的Hugepages數目。即使oraclesga已經分配了這部分記憶體,但是如果沒有實際寫入,那麼看到的還是Free的。這是很容易誤解的地方。
HugePages_Rsvd為已經被分配預留但是還沒有使用的page數目。在Oracle剛剛啟動時,大部分記憶體應該都是Reserved並且Free的,隨著oracle SGA的使用,Reserved和Free都會不斷的降低。
HugePages_Free-HugePages_Rsvd 這部分是沒有被使用到的記憶體,如果沒有其他的oracle instance,這部分記憶體也許永遠都不會被使用到,也就是被浪費了。
4. HugePages和oracle AMM(自動記憶體管理)是互斥的,所以使用HugePages必須設定記憶體參數MEMORY_TARGET / MEMORY_MAX_TARGET 為0。
3. 配置HugePages
3.1 修改核心參數memlock
修改核心參數memlock,單位是KB,如果記憶體是16G,memlock的大小要稍微小於實體記憶體。計劃lock 12GB的記憶體大小。參數設定為大於SGA是沒有壞處的。
以root使用者登入兩台資料庫伺服器,編輯limits.conf檔案:
node74:~ # vi /etc/security/limits.conf
增加以下兩行內容:
* soft memlock 12582912
* hard memlock 12582912
3.2 驗證memlock limit
重新登入root和oracle使用者,檢查memlocklimit
node74:~ # ulimit -l
12582912
oracle@node74:~> ulimit -l
12582912
3.3 禁用AMM
如果使用11G及以後的版本,AMM已經預設開啟,但是AMM與Hugepages是不相容的,必須先disable AMM。禁用AMM的步驟如下:
3.3.1 關閉資料庫執行個體
已oracle使用者登入兩台資料庫伺服器,通過sqlplus關閉2個資料庫執行個體。
oracle@node74:~> sqlplus / as sysdba
SQL> shutdown immediate
3.3.2 建立pfile
以oracle使用者登入其中一台主機,執行以下命令建立pfile:
oracle@node74:~> sqlplus / as sysdba
SQL> create pfile='/home/oracle/pfile.ora' fromspfile=’+DG_ORA/orcl/spfileorcl.ora’;
3.3.3 編輯pfile
編輯pfile,刪除memory_max_target和memory_target參數:
oracle@node74:~> vi /home/oracle/pfile.ora
刪除下面幾行:
orcl1.memory_max_target=11114905600
orcl2.memory_max_target=11114905600
*.memory_max_target=0
orcl1.memory_target=11114905600
orcl2.memory_target=11114905600
*.memory_target=0
修改後儲存檔案。
3.3.4 建立spfile
執行以下命令建立spfile:
oracle@node74:~> sqlplus / as sysdba
SQL> create spfile='+DG_ORA/orcl/spfileorcl.ora'from pfile='/home/oracle/pfile.ora';
3.3.5 修改系統參數kernel.shmall
Kernel.shmall是系統一次可以使用的最大共用記憶體大小。單位是page(4KB)。禁用AMM後,需要修改系統參數kernel.shmall,該參數設定過小的話,可能會導致資料庫啟動失敗ORA-27102(詳見附錄4.2)。
ORACLE建議將其設定為系統中所有資料庫執行個體的SGA總和。例如SGA總和為9GB,則需要設定kernel.shmall=9*1024*1024/4=2359296。
以root使用者登入兩台資料庫伺服器,編輯sysctl.conf檔案。
node74:~ # vi /etc/sysctl.conf
修改kernel.shmall參數:
kernel.shmall = 2359296
執行sysctl –p使配置生效:
node74:~ # sysctl -p
3.3.6 啟動資料庫執行個體
以oracle使用者登入兩台資料庫伺服器,通過sqlplus啟動2個資料庫執行個體。
oracle@node74:~> sqlplus / as sysdba
SQL> startup
3.4 計算需要使用的hugepage頁面大小
確保全部執行個體都已經啟動(包括ASM) ,然後以root使用者運行hugepages_settings.sh(指令碼內容見附錄4.1)去評估需要設定的Hugepages的大小。
node74:/home/oracle # ./hugepages_settings.sh
This script is provided by Doc ID 401749.1 from MyOracle Support
(http://support.oracle.com) where it is intended tocompute values for
the recommended HugePages/HugeTLB configuration forthe current shared
memory segments. Before proceeding with the executionplease make sure
that:
* OracleDatabase instance(s) are up and running
* OracleDatabase 11g Automatic Memory Management (AMM) is not setup
(See Doc ID749851.1)
* The sharedmemory segments can be listed by command:
# ipcs -m
Press Enter toproceed...
----直接按Enter鍵
Recommended setting: vm.nr_hugepages = 4611
也可以手工計算:
nr_hugepages>=SGA_Target/Hugepagesize
=9G*1024M/2M
=4608
取一個比4608稍大的值即可。
3.5 修改vm.nr_hugepages參數
以root使用者登入兩台資料庫伺服器,編輯/etc/sysctl.conf:
node74:~ # vi /etc/sysctl.conf
修改vm.nr_hugepages參數為上一步中計算出來的值:
vm.nr_hugepages = 4611
執行sysctl –p使配置生效:
node74:~ # sysctl -p
3.6 停止資料庫執行個體,重啟作業系統
停止所有資料庫執行個體,重啟作業系統。(理論上不需要重啟作業系統,建議重啟)
3.7 檢查設定是否生效
系統重啟後,啟動全部的資料庫,通過以下命令檢查配置是否生效:
node74:~ # grep HugePages /proc/meminfo
HugePages_Total: 4611
HugePages_Free: 2394
HugePages_Rsvd: 2387
HugePages_Surp: 0
HugePages_Free< HugePages_Total則說明Hugepages已經生效,同時HugePages_Rsvd不為0。
4. 附錄 4.1 指令碼hugepages_settings.sh
#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
#
# This script is provided by Doc ID 401749.1 from My Oracle Support
# http://support.oracle.com
# Welcome text
echo "
This script is provided by Doc ID 401749.1 from My Oracle Support
(http://support.oracle.com) where it is intended to compute values for
the recommended HugePages/HugeTLB configuration for the current shared
memory segments. Before proceeding with the execution please make sure
that:
* Oracle Database instance(s) are up and running
* Oracle Database 11g Automatic Memory Management (AMM) is not setup
(See Doc ID 749851.1)
* The shared memory segments can be listed by command:
# ipcs -m
Press Enter to proceed..."
read
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
# Initialize the counter
NUM_PG=0
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | awk '{print $5}' | grep "[0-9][0-9]*"`
do
MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
if [ $MIN_PG -gt 0 ]; then
NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
fi
done
RES_BYTES=`echo "$NUM_PG * $HPG_SZ * 1024" | bc -q`
# An SGA less than 100MB does not make sense
# Bail out if that is the case
if [ $RES_BYTES -lt 100000000 ]; then
echo "***********"
echo "** ERROR **"
echo "***********"
echo "Sorry! There are not enough total of shared memory segments allocated for
HugePages configuration. HugePages can only be used for shared memory segments
that you can list by command:
# ipcs -m
of a size that can match an Oracle Database SGA. Please make sure that:
* Oracle Database instance is up and running
* Oracle Database 11g Automatic Memory Management (AMM) is not configured"
exit 1
fi
# Finish with results
case $KERN in
'2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
'2.6') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
*) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End
4.2 資料庫啟動報錯ORA-27102
Upon startup of Linux database getORA-27102: out of memory Linux-X86_64 Error: 28: No space left on device
Subject:
Upon startup of Linux database getORA-27102: out of memory Linux-X86_64 Error: 28: No space left on device
Doc ID:
Note:301830.1
Type:
PROBLEM
Last Revision Date:
31-OCT-2008
Status:
PUBLISHED
In this Document
Symptoms
Changes
Cause
Solution
References
--------------------------------------------------------------------------------
Applies to:
OracleServer- Enterprise Edition - Version: 9.2.0.4 to 11.1.0.6
UnitedLinux x86-64
Red Hat Enterprise Linux Advanced Serverx86-64 (AMD Opetron Architecture)
x86 64 bit
Symptoms
When trying to increase the SGA to approachhalf available RAM with an Oracle 64bit version on a Linux 64bit operatingsystem, even though shmmax is set to match half the amount of RAM, youget the following error when trying to start the instance:
SQL> startup nomount
ORA-27102: out of memory
Linux-x86_64 Error: 28: No space left ondevice
Changes
shmall is too small, most likely is set tothe default setting of 2097152
$ cat /proc/sys/kernel/shmall
2097152
Cause
shmall is the total amount of sharedmemory, in pages, that the system can use at one time.
Solution
Set shmall equal to the sum of all the SGAson the system, divided by the page size.
The page size can be determined using thefollowing command:
$ getconf PAGE_SIZE
4096
For example, if the sum of all the SGAs onthe system is 16Gb and the result of '$ getconf PAGE_SIZE' is 4096 (4Kb)then set shmall to 4194304 (4Mb)
As the root user set the shmall to 4194304in the /etc/sysctl.conf file:
kernel.shmall = 4194304
then run the following command:
# sysctl –p
# cat /proc/sys/kernel/shmall
4194304
NOTE:
The above command loads the new value and areboot is not necessary
Switch back to being the oracle user andretry the startup command.
References
Note 169706.1 - Oracle? Database onAIX?,HP-UX?,Linux?,Mac OS? X,Solaris?,Tru64 Unix? Operating SystemsInstallation and Configuration Requirements Quick Reference (8.0.5 to 11.1)
Keywords
NO~SPACE~LEFT~ON~DEVICE ; START~INSTANCE ;OUT~OF~MEMORY ; 64BIT ;