3.2 Paging Space,交换区
UNIX系统都采用虚拟内存结构,交换区与物理内存一起提供对虚拟内存的支持。程序直接访问虚拟内存空间(Virtual Address Space),虚拟内存空间通过操作系统的虚拟内存管理系统与物理内存和交换区(就是磁盘上的一块区域)对应。当程序访问的虚拟内存数据不在物理内存的时候,硬件系统会产生指令/数据访问中断,该中断调用例程将需要的数据由磁盘上的交换区调入物理内存。
另一方面,当物理内存没有足够的空间存放执行数据的时候,虚拟内存管理程序执行一种被称为“偷页”的算法(UNIX中以页为单位分配、使用内存,AIX中每页为4KB),依次询问每个内存页(在物理内存中)最近有没有被访问过,如果该页没有被访问过,就认为该页内存可以释放掉。在释放内存之前,还要判断此内存页是计算内存还是文件内存,如果是计算内存,需要先将内存页内的数据保存到磁盘(交换区,即交换到磁盘上,把内存空间留给需要内存的程序,交换区结构如图3-3所示),这种操作被称为“page out”。如果是文件内存,就简单了,可以直接丢弃掉。关于什么是计算内存,什么是文件内存,我们将在下一节详细介绍。当系统需要使用的数据恰好在被交换到磁盘上的内存页的时候,虚拟内存管理会产生一个中断,暂停程序执行,随后它自动将磁盘上的内存页读回物理内存,这就是“page in”操作。
图3-3 交换区结构示意图
3.2.1 交换区多大比较合适
对于AIX系统,传统的交换区配置规则是与内存相等或者大小是其两倍,如果内存很大,可以配置为与内存的大小相等或稍小。由于目前系统的内存通常配置得较大,所以交换区大小不需要再特别精确地计算,而且对系统的影响也几乎可以忽略不计。通常可以根据运行软件的情况(参考软件的安装、规划手册)进行设置,一些数据库和应用程序通常需要较大的交换区,例如SAP,建议配置为10~30GB的交换区,如果物理内存更多,则交换区可以配置到近100GB;而另一些则可能需要很小的交换区,例如网络服务程序,几百兆字节的交换区就足够了。
以上只是一些经验值,每个系统交换区的最佳配置大小需要根据经验现场分析,如果运行过程中,经常发现交换区使用率超过50%,建议适当扩大交换区大小;而如果交换区经常只使用不超过10%,使可以适当减少交换区空间。另外要注意,如果操作系统版本很低(例如4.3.3),由于不能动态缩小交换区,不要将交换区一次扩得比较大,可以渐渐增加,但也不要过于频繁,那样做会产生很多不连续的交换区“碎块”,从而影响性能,所以最好能2~3次就能达到一个合理的数值,以后找时间通过“磁盘整理”消除碎块。
3.2.2 分配交换区的建议规则
建议规则是:将需要的交换区空间分成几乎相等的几份,分别放置在rootvg的各个硬盘上,有几个硬盘就分几份(可以镜像,实际可用的份数就会少一半),但最好不要放在外置硬盘之上。例如一台4GB内存的主机,有4块内置硬盘,可以配置2个交换区,每个大小2GB,分别放在两个内置硬盘上,并镜像到另两块硬盘。也有不对交换区进行镜像的建议,这样可以提高速度,但是如果一块盘发生故障,可能会引起宕机,需要管理员在可靠性和性能之间做出选择。
分配交换区的命令:
#smitty pgsp Paging Space Move cursor to desired item and press Enter. List All Paging Spaces 显示交换区大小 Add Another Paging Space 增加新交换区 Change / Show Characteristics of a Paging Space更改交换区特性(例如大小) Remove a Paging Space 删除一个交换区 Activate a Paging Space 激活一个交换区 Deactivate a Paging Space 停止一个交换区
3.2.3 如何缩小默认的交换区(hd6)
缩小交换区并不困难,但是很麻烦(在AIX 5.1以后版本可以动态删除交换区,但如果只有一个交换区,还是有些问题,因为系统要使用一个“临时”的交换区,需要额外的磁盘空间),所以尽量不要建出一个过大的交换区为好。如果已经如此,那么:
先建一个临时的交换区空间:mkps -s 20 -a rootvg(生成新交换区paging00)
设置下次启动时不使用默认的交换区hd6:
#chps -a n hd6
编辑/sbin/rc.boot,将swapon /dev/hd6改为swapon /dev/paging00。
因为原来的系统dump设备为/dev/hd6,在删除原有的交换区之前,也要改到新的交换区上:
#sysdumpdev -p /dev/paging00
更新启动逻辑卷的信息:
#bosboot -a -d hdisk0 → 在hdisk0上重新写入引导程序 #shutdown -Fr → 重新引导系统
删除原来的hd6,创建新的合适大小的交换区:
#rmps hd6 #mklv -y hd6 -t paging rootvg <size of PS in PP numbers>
重新编辑/sbin/rc.boot文件,将交换区换为原来的/dev/hd6:
#swapon /dev/hd6
将dump设备改回hd6:
#sysdumpdev -p /dev/hd6
重新设置启动逻辑卷信息:
#bosboot -a -d hdisk0
将当前使用的临时交换区设置为下次启动不激活:
#chps -a n /dev/paging00
重启,删除临时的交换区:
#rmps paging00
现在可以检查一下结果了:
#lsps -a
3.2.4 交换区不断增长,直至100%怎么办
如果交换区持续增长则首先需要确认交换区的大小是否足够,如果不够则需要增加。一般来说交换区的分配如果合理,交换区的利用率会固定在一个稳定的数值。如果交换区的使用率持续增长至100%,则会引起新程序无法执行,或者宕机。可能的原因是执行了非常消耗内存的程序或者存在内存泄漏问题。
用lsps -a命令可以查看交换区使用率,而当系统交换区接近100%时,很明显的迹象是系统会有如下提示之一:
INIT: Paging space is low
ksh: cannot fork no swap space
Not enough memory
Fork function failed
fork () system call failed
Unable to fork, too many processes
Fork failure - not enough memory available
Fork function not allowed. Not enough memory available.
Cannot fork: Not enough space
此时你可能可以“眼疾手快”地通过关闭(kill)几个不重要的程序,释放出一些内存,给你一些缓冲时间,扩大交换区。但通常你没有足够的时间,机器马上变得很慢,输入任何命令都没反应,或者提示以上某一条信息,所有需要新启动服务程序的服务也不能工作(例如telnet),但是往往已经启动的程序还能够正常使用,特别是启动后就不再继续申请内存的程序,例如Oracle。此时的唯一解决办法就是坚持到可以停机的时候,重新启动计算机,或者通过其他方式,停止一些消耗内存比较大的程序(例如通过sqlplus访问Oracle,将其停掉),获得一些内存,然后再用其他命令处理,杀掉内存占用“大户”。因此,如果交换区使用率经常大幅度波动的话,经常查看交换区使用率非常有必要。
vmstat命令可以查看所有系统使用的虚拟内存,就是vmstat中“avm”一项。(avm的含义是Avtive Virtual Memory,而不是availabile memory!)AVM代表了物理内存与交换区使用的空间的总和(以4KB为单位)。如果avm一项在持续增长,就可能有内存泄漏,此时交换区使用率也一定在增长。但只用vmstat还无法定位到具体程序,不可能所有的程序都在泄漏内存!那就需要更具体的定位方案了。
3.2.5 交换区分配策略
AIX系统有三种交换区分配策略。
1.Late Page Space Allocation(LPSA),交换区滞后分配策略
在AIX 4.3.2版本以前,操作系统默认采用滞后分配策略。滞后分配策略是当某个进程申请内存的同时,虚拟内存就给它分配了空间,但是只有当这块内存真正需要交换到磁盘上去的时候,才将磁盘交换区上的空间与此内存页面相关联。因此这种策略不能保证当需要进行磁盘交换的时候有足够的交换区空间,因为可能有别的程序“抢先”进行磁盘交换,而占据了所有的磁盘空间交换区。
2.Early Page Space Allocation(EPSA),交换区预先分配策略
为了确保进程不会由于缺少交换区而被“杀”掉,可以使用预先分配策略。通过设置环境变量PSALLOC为early,将使此后执行的程序采用预先分配策略。采用预先分配策略可以确保进程有交换区(只要进程能够成功申请内存,磁盘上就保留出对应的空间,并且不能共用)。如果采用了预先分配策略,并且希望节省CPU资源,可以考虑设置另一个环境变量NODISCLAIM=true,当程序释放内存的时候,磁盘交换区上预留的空间并不立刻释放,这样可以减少部分CPU的操作。
3.Deferred Page Space Allocation(DPSA),交换区延迟分配策略
从AIX 4.3.2开始增加了一种延迟分配策略。与滞后分配策略类似,延迟分配策略更为“延迟”,直到需要进行磁盘交换的时候,才在交换区空间进行分配,所以不会发生所分配的空间被抢占的情况,但是由于需要临时进行空间分配,CPU计算更为复杂,对于有频繁磁盘交换的系统,会影响一定的性能。
只要内存数据被交换到某块磁盘空间,即使内存数据被page in回内存,磁盘空间依然保留。因此交换区使用百分比可能并不能真实反映真正实用的磁盘交换区情况(比真正使用量稍大),因为某些磁盘数据可能已经被交换回内存,只有当使用此内存的进程释放了内存后,磁盘交换区才将分配空间释放掉。
通过设定环境变量可以控制系统对于下一个执行程序的交换区分配策略。例如执行:
#PSALLOC=early;export PSALLOC
可以让系统执行下一个程序时采用EPSA(提前分配)策略。系统缺省是defer策略。
3.2.6 交换区分配问题解释
内存、交换区分配中有许多概念非常令人困惑,其中一些与管理有关,另一些则与性能有关,而这两大部分,都是小型机技术中的重中之重。在3.2.1节“交换区多大比较合适”一节中已经介绍了一些关于交换区大小的经验,那么这些经验是如何得来的呢?任何经验的背后,都是有理论依据的,但可能由于没有经过仔细分析而不为人所知。
交换区本质上就是保存程序、数据的空间,由于磁盘通常用于保存最终结果,而中间过渡的数据,由于经常被频繁访问,因此被存储到内存中,特别是很多程序并没有自行处理临时文件的机制,不会主动将内存中的数据写入磁盘,因为这需要额外一套复杂的机制去处理,处理不好,还会引起严重的性能问题,甚至导致程序故障。因此,将内存中暂时不用的数据临时存储到硬盘,当程序需要这部分数据的时候,再把它调回内存中就成为操作系统责无旁贷的工作。对应用程序来说,它根本不知道自己的代码和数据在内存和硬盘中换来换去,而以为都是在内存中,因此避免了编程的复杂性;多个程序都“共用”操作系统提供的内存、硬盘交换功能,显然代码效率提高,也更容易优化。
这就是操作系统的发展趋势:程序为了极端的性能、效率,自己研发出某些功能,当这些功能开始被众多程序普及使用后,操作系统就“接手”这些功能,集成到操作系统中,成为一项公用的功能,应用程序也因此简化了许多,当然,它又会去继续研究其他好用的功能。逻辑卷管理、交换区,甚至网络通信能力都是这样一步步从专用程序演化为操作系统的集成功能,最后甚至成为某个独立与服务器的硬件设备(例如路由器)。
了解了交换区的历史背景,我们就可以回归交换区的本质去探讨交换区使用和涉及的性能问题:交换区的大小当然是够用就行!太大,暂用额外的磁盘空间,浪费;太小,当程序需要的时候,没有足够的虚拟内存空间使用;同时,程序所要经常访问的数据容量,必须小于物理内存数量,否则就会有严重的性能问题。由于这个原因,交换区的大小设置没有绝对的要求,需要根据应用程序的要求进行设置。同时要注意:所有运行中的应用程序“经常”要访问的内存,一定要少于真正的物理内存数量,尽管对于程序来说,它自己分不出交换区和物理内存,而性能却差很多,例如几十倍的差距!
不同程序特性决定了系统配置交换区的大小需求。如果程序一次性申请内存,并且很少再额外申请内存(例如Oracle数据库),则交换区并不重要,只要确保指定分配给此程序需要的内存少于物理内存(一般少于80%的物理内存)就可以了;但是如果此程序要求的内存非常大,或者经常进行申请/释放内存操作,则交换区就需要适当增大,具体大小一般根据程序的需求来定;还有一种类型的程序属于长时间运行,需要访问大量的数据,但访问很不集中,就是大部分时间都在闲置或一段时间内仅需要一小块数据(如SAP应用),这样内存中长时间不使用的数据会需要从内存中转储到交换区,也需要比较大的交换区。
如果你并不清楚程序的特性,可以在一段时间对程序进行“监视”,观察程序的内存使用情况,最终设定一个合适的内存交换区大小。