使用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 ;




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章