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

[email protected]:~> ulimit -l

12582912

3.3 禁用AMM

如果使用11G及以后的版本,AMM已经默认开启,但是AMM与Hugepages是不兼容的,必须先disable AMM。禁用AMM的步骤如下:

3.3.1 关闭数据库实例

已oracle用户登录两台数据库服务器,通过sqlplus关闭2个数据库实例。

[email protected]:~> sqlplus / as sysdba

SQL> shutdown immediate

3.3.2 创建pfile

以oracle用户登录其中一台主机,执行以下命令创建pfile:

[email protected]:~> 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参数:

[email protected]:~> 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:

[email protected]:~> 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个数据库实例。

[email protected]:~> 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 ;

时间: 2024-12-04 14:15:55

使用HugePages优化内存性能的相关文章

Android内存性能优化(内部资料总结)

刚入门的童鞋肯能都会有一个疑问,Java不是有虚拟机了么,内存会自动化管理,我们就不必要手动的释放资源了,反正系统会给我们完成.其实Java中没有指针的概念,但是指针的使用方式依然存在,一味的依赖系统的gc,很容易就造成了内存的浪费.   Java基于垃圾回收的内存机制 Java的内存管理机制会自动回收无用对象所占用的内存,减轻手工管理内存的负担 1.C/C++: 从申请.使用.释放都需要手工管理 2.Java:无用的对象的内存会被自动回收 什么样的对象是无用的对象 1.Java通过引用来操作一

Android性能优化之巧用软引用与弱引用优化内存使用

前言: 从事Android开发的同学都知道移动设备的内存使用是非常敏感的话题,今天我们来看下如何使用软引用与弱引用来优化内存使用.下面来理解几个概念. 1.StrongReference(强引用) 强引用是我们最最常见的一种,一般我们在代码中直接通过new出来的对象等,都是强引用,强引用只要存在没有被销毁,内存就不会被系统回收.我们以生成Bitmap为例如下: Bitmap imageBitmap = readBitmapFromResource(getResources(), R.mipmap

Android内存性能优化(内部资料总结) eoe转载

刚入门的童鞋肯能都会有一个疑问,Java不是有虚拟机了么,内存会自动化管理,我们就不必要手动的释放资源了,反正系统会给我们完成.其实Java中没有指针的概念,但是指针的使用方式依然存在,一味的依赖系统的gc,很容易就造成了内存的浪费. Java基于垃圾回收的内存机制 Java的内存管理机制会自动回收无用对象所占用的内存,减轻手工管理内存的负担 1.C/C++: 从申请.使用.释放都需要手工管理 2.Java:无用的对象的内存会被自动回收 什么样的对象是无用的对象 1.Java通过引用来操作一个具

记一次vue长列表的内存性能分析和优化

好久没写东西,博客又长草了,这段时间身心放松了好久,都没什么主题可以写了 上周接到一个需求,优化vue的一个长列表页面,忙活了很久也到尾声了,内存使用和卡顿都做了一点点优化,还算有点收获 写的有点啰嗦,可以看一下我是怎么进行这个优化的,也许有点帮助呢 这个长列表页面,其实是一个实时日志上报的页面,随着页面打开时间的增加,日志数量也会增多,常规的页面布局和渲染免不了会遇到性能问题. 使用了vue框架,框架内部的虚拟DOM和组件缓存已经做了一些优化,比起原生实现是有了一些优化处理. 但这个页面是用到

C++ Primer 学习笔记_98_特殊工具与技术 --优化内存分配

特殊工具与技术 --优化内存分配 引言: C++的内存分配是一种类型化操作:new为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自动运行合适的构造函数来初始化每个动态分配的类类型对象. new基于每个对象分配内存的事实可能会对某些类强加不可接受的运行时开销,这样的类可能需要使用用户级的类类型对象分配能够更快一些.这样的类使用的通用策略是,预先分配用于创建新对象的内存,需要时在预先分配的内存中构造每个新对象. 另外一些类希望按最小尺寸为自己的数据成员分配需要的内存.例如,

C++ Primer 学习笔记_99_特殊工具与技术 --优化内存分配[续1]

特殊工具与技术 --优化内存分配[续1] 三.operator new函数和operator delete 函数 – 分配但不初始化内存 首先,需要对new和delete表达式怎样工作有更多的理解.当使用new表达式 string *sp = new string("initialized"); 的时候,实际上发生三个步骤: 1)首先,表达式调用名为operator new 的标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象; 2)接下来,运行该类型的一个构造函数

Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间

Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何在 Windows 上安装并使用,一些 GUI 工具和自己简单封装的 RedisHelper. <Redis 小白指南(二)- 聊聊五大类型:字符串.散列.列表.集合和有序集合>讲的是 Redis 中最核心的内容,最常用的就是和数据类型打交道. 目录 事务 过期时间 消息通知 管道 优化内存空间

[转]Oracle DB 通过SQL 优化管理性能

? 将SQL 优化指导用于: – 确定使用资源最多的 SQL 语句 – 优化使用资源最多的 SQL 语句 ? 使用SQL 访问指导优化工作量 SQL 优化 SQL 优化进程 ? 确定没有很好地优化的SQL 语句. ? 优化各条语句. ? 优化整个应用程序. 一般情况下,效果最明显的优化工作是SQL 优化.没有很好地优化的SQL 会不必要地使用过多资源.这种低效率会降低可伸缩性.使用更多的OS 和数据库资源并增加响应时间.要对没有很好地优化的SQL 语句进行优化,必须先确定这些语句,然后再进行优化

Android 性能优化 五 性能分析工具dumpsys的使用

Android提供的dumpsys工具可以用于查看感兴趣的系统服务信息与状态,手机连接电脑后可以直接命令行执行adb shell dumpsys 查看所有支持的Service但是这样输出的太多,可以通过dumpsys | grep "DUMP OF SERVICE" 仅显示主要的Service的信息 一.列出dumpsys所有支持命令 > adb shell $ dumpsys | grep "DUMP OF SERVICE" 以下是在我个人三星S3手机上的输