在Linux環境性能優化實踐中,HugePage是一個經常提到的方法。簡單的說,HugePage就是Linux內核上一種是用內存塊的方法。作為傳統4K Page的替代,HugePage在大部分場景下可以提升Oracle實例的運行性能效率。
本篇介紹如何進行HugePage配置和Oracle環境使用。
1、HugePage介紹
HugePage廣泛啟用開始於Kernal 2.6,一些版本下2.4內核也可以是用。在操作系統Linux環境中,內存是以頁Page的方式進行分配,默認大小為4K。如果需要比較大的內存空間,則需要進行頻繁的頁分配和管理尋址動作。
HugePage是傳統4K Page的替代方案。顧名思義,是用HugePage可以讓我們有更大的內存分頁大小。無論是HugePage還是傳統的正常Page,這個過程都涉及到OS內存尋址過程。
當一個進程訪問內存的時候,並不是直接進行內存位置訪問,是需要通過Page Table進行轉移變換。在使用HugePage的情況下,PageTable具有了額外的屬性,就是判斷該頁記錄是HugePage還是Regular Page。
在Oracle運行環境中開啟HugePage是有很多好處的。具體如下:
ü 非Swap內存:當開啟HugePage的時候,HugePage是不會Swap的;
ü 減少TLB(Translation Look aside Buffer)負擔:TBL是在CPU里面的一塊緩沖區域,其中包括了部分Page Table內容。使用HugePage可以減少TLB工作負載;
ü 減少Page Table空間負載:在PageTable管理中,每條Page記錄是要占據64byte的空間的。也就是說,如果一塊50G的RAM,4k大小的PageTable要有800MB左右;
ü 減少PageTable檢索負載:更小的PageTable意味着更快的檢索定位能力;
ü 內存性能提升:Page數量減少、大小的增加,減少了管理過程的復雜性,進一步減少了瓶頸出現的概率;
對於Oracle而言,實例運行環境(Database和ASM)都面對一個HugePage優化的問題。
2、基礎環境准
我們選擇RedHat 5.3版本,也就是Kernel2.6進行實驗。
[oracle@SimpleLinux ~]$ uname -r
2.6.18-128.el5
此時Oracle實例為11gR2(11.2.0.3),運行在AMM內存管理方式下。共享內存段信息如下。
[oracle@SimpleLinux ~]$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 32768 oracle 640 4096 0
0x00000000 65537 oracle 640 4096 0
0x01606d30 98306 oracle 640 4096 0
[oracle@SimpleLinux ~]$ grep Huge /proc/meminfo
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 4096 kB
注意兩個問題:一個是當前我們在meminfo中沒有啟用HugePage,所以沒有對應的記錄。另一個是AMM下,ipcs –m顯示出的共享內存大小只有三個每個大小4096bytes。
這個問題是比較復雜的,本篇就介紹一個開頭。在10g中,Oracle引入了sga_target系列參數,實現了ASMM(Automatic Shared Memory Management)。ASMM的本質是實現SGA和PGA內部各個池之間的動態調整。但是在11g中,推出了AMM(Automatic Memory Management),實現了PGA和SGA之間的調節。
AMM其實是復雜的。SGA在Linux中是通過系統共享內存實現,而PGA是通過進程私有空間實現。AMM實際上最大的功能是將SGA和PGA空間調節的通道打通,這必然帶來對原有SGA共享內存方式架構的影響。在AMM時,ipcs –m顯示的虛擬空共享段就是實際效果的一部分。
2、設置用戶內存配置
啟用HugePage的第一步就是進行用戶參數限制打通,當前內存大小如下:
--內存信息
[root@SimpleLinux ~]# free -t
total used free shared buffers cached
Mem: 918380 205044 713336 0 14744 152996
-/+ buffers/cache: 37304 881076
Swap: 2455788 0 2455788
Total: 3374168 205044 3169124
修改/etc/security/limits.conf參數文件,添加數據庫實例用戶的memlock限制。
[root@SimpleLinux ~]# cat /etc/security/limits.conf
# /etc/security/limits.conf
#
(篇幅原因,有省略……)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
#ftp hard nproc 0
#@student - maxlogins 4
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
oracle soft memlock 918380
oracle hard memlock 918380
# End of file
這個過程中使用memlock標記,用於設置每個用戶允許的最大內存使用情況。這個取值可以設置為數據庫服務器物理內存大小。
切換到指定用戶(oracle),查看設置。
[oracle@SimpleLinux ~]$ ulimit -l
918380
3、Oracle設置
如果是使用11g Oracle版本,一定需要進行額外的配置,就是將使用的AMM退化為ASMM。在早期的11.2.0.1版本中,這個步驟很重要。因為AMM是不支持HugePage的,如果強在AMM+HugePage模式下打開數據庫,是會遇到失敗信息。
在最新的11.2.0.2版本以及之后,引入了參數use_large_pages,避免了這樣的問題。但是AMM與HugePage不兼容的情況,還是存在。
當前是使用AMM的數據庫。
SQL> show parameter target
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
archive_lag_target integer 0
db_flashback_retention_target integer 1440
fast_start_io_target integer 0
fast_start_mttr_target integer 0
memory_max_target big integer 360M
memory_target big integer 360M
parallel_servers_target integer 16
pga_aggregate_target big integer 0
sga_target big integer 0
AMM的關鍵在於兩個方面,一個是memory_target和memory_max_target設置非空。另一個是sga_target和pga_aggregate_target參數設置為空。如果要關閉AMM,退化開啟ASMM,就需要進行實例啟動參數的設置。
說明:本篇不是以修改AMM到ASMM作為重點,這部分內容略,留待其他文章進行說明。
修改之后,需要重啟服務器,因為一些參數屬於靜態參數。
SQL> conn / as sysdba
Connected.
SQL> show parameter target
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
archive_lag_target integer 0
db_flashback_retention_target integer 1440
fast_start_io_target integer 0
fast_start_mttr_target integer 0
memory_max_target big integer 0
memory_target big integer 0
parallel_servers_target integer 16
pga_aggregate_target big integer 108M
sga_target big integer 252M
注意,此時共享內存機制才真正實現,我們從ipcs –m中,可以看到真正的共享段。
[oracle@SimpleLinux dbs]$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 327680 oracle 640 4194304 27
0x00000000 360449 oracle 640 260046848 27
0x01606d30 393218 oracle 640 4194304 27
4、經驗腳本計算HugePage最大值
HugePage 有兩種方法:
一:使用要設置的SGA_TARGET的值加1G/Huagepagesize 比如 SGA_TARGET 為19G,HugePagesize 為2M, 則Hugepage的個數為 (19+1)*1024/2 = 10240
二:使用腳本: 在MOS 401749.1中,Oracle推薦了一個Shell腳本來計算HugePage值。運行這個腳本,將計算出的取值設置在系統參數中。hugepages_settings.sh的腳本詳細信息請見文末
執行腳本,注意這個過程中要求Oracle所有實例,包括數據庫和ASM都啟動、AMM關閉,以及SGA大小超過100M。
[oracle@SimpleLinux upload]$ ./hugepages_settings.sh
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 note following:
* For ASM instance, it needs to configure ASMM instead of AMM.
* The 'pga_aggregate_target' is outside the SGA and
you should accommodate this while calculating SGA size.
* In case you changes the DB SGA size,
as the new SGA will not fit in the previous HugePages configuration,
it had better disable the whole HugePages,
start the DB with new SGA size and run the script. again.
And 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...
Recommended setting: vm.nr_hugepages = 67
將計算出的67更改參數/etc/sysctl.conf。
--設置參數
[root@SimpleLinux ~]# vi /etc/sysctl.conf
(添加內容如下……)
vm.nr_hugepages = 67
"/etc/sysctl.conf" 49L, 1325C written
使用sysctl –p生效設置。
[root@SimpleLinux ~]# sysctl -p
net.ipv4.ip_forward = 0
(篇幅原因,有省略……)
net.core.wmem_max = 1048586
vm.nr_hugepages = 67
5、HugePage啟動檢驗
設置之后,最好重新啟動服務器,包括Oracle。
[oracle@SimpleLinux ~]$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 32768 oracle 640 4194304 26
0x00000000 65537 oracle 640 260046848 26
0x01606d30 98306 oracle 640 4194304 26
[oracle@SimpleLinux ~]$ grep Huge /proc/meminfo
HugePages_Total: 67
HugePages_Free: 3
HugePages_Rsvd: 0
Hugepagesize: 4096 kB
在meminfo文件中,可以查到HugePages的信息,說明啟用成功。
6、總結
隨着Linux+PC的服務器模式普及,我們會在實際工作中見到越來越多的Linux服務器和遇到越來越多的Linux系統。HugePage作為一種常用的性能優化手段,需要關注學習。
附: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 note following:
* For ASM instance, it needs to configure ASMM instead of AMM.
* The 'pga_aggregate_target' is outside the SGA and
you should accommodate this while calculating SGA size.
* In case you changes the DB SGA size,
as the new SGA will not fit in the previous HugePages configuration,
it had better disable the whole HugePages,
start the DB with new SGA size and run the script again.
And 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}'`
if [ -z "$HPG_SZ" ];then
echo "The hugepages may not be supported in the system where the script is being executed."
exit 1
fi
# Initialize the counter
NUM_PG=0
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | cut -c44-300 | awk '{print $1}' | 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.2') echo "Kernel version $KERN is not supported. Exiting." ;;
'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" ;;
esac
# End