风行者的遗产好看吗:HP-UX top 输出中实存(real memory)/虚存(virtual memory)数据解释

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 16:09:34
top 是 Unix/Linux 中一个非常直观的性能观察工具,它能把与系统负载、CPU、内存、进程、I/O 相关的性能数据展示在一个画面中。在 AIX 中 top 有另一个名字叫 topas,今天想谈谈 HP-UX 中的 top,在 HP-UX 中 top 输出最让人困惑的是关于内存的一组数据,下面是 HP-UX 中一个 top 输出:

JHDB0100@oracle[/var/adm/syslog]top
System: JHDB0100                                      Wed Nov  3 10:19:48 2010
Load averages: 0.37, 0.40, 0.40
341 processes: 317 sleeping, 23 running, 1 zombie
Cpu states:
CPU   LOAD   USER   NICE    SYS   IDLE  BLOCK  SWAIT   INTR   SSYS
 0    0.36  25.7%   0.0%   2.4%  71.9%   0.0%   0.0%   0.0%   0.0%
 1    0.39  41.9%   0.0%   1.8%  56.3%   0.0%   0.0%   0.0%   0.0%
 2    0.36  32.3%   0.0%   2.0%  65.7%   0.0%   0.0%   0.0%   0.0%
 3    0.38  42.9%   0.0%   2.0%  55.1%   0.0%   0.0%   0.0%   0.0%
---   ----  -----  -----  -----  -----  -----  -----  -----  -----
avg   0.37  35.7%   0.0%   2.2%  62.2%   0.0%   0.0%   0.0%   0.0%

Memory: 3823384K (1165440K) real, 4413348K (1410548K) virtual, 3702400K free  Pa
ge# 1/38

CPU TTY  PID USERNAME PRI NI   SIZE    RES STATE    TIME %WCPU  %CPU COMMAND
 0   ?  4630 oracle   240 20  3942M  8320K run   5542:35 53.65 53.56 oracleodsbp
 0   ?  4650 oracle   154 20  3942M  8512K sleep 6003:43 16.88 16.85 oracleodsbp
 1   ?  4626 oracle   212 20  3942M  8384K run   5727:08 13.76 13.73 oracleodsbp
 3   ? 26787 oracle   154 20  3962M 28672K sleep    1:20  6.55  6.54 oracleodsbp
 3   ? 28452 oracle   183 20  3962M 28672K run      0:04  6.55  6.43 oracleodsbp
 3   ? 27675 oracle   154 20  3962M 28672K sleep    0:43  6.38  6.37 oracleodsbp
 2   ? 28044 oracle   154 20  3962M 28672K sleep    0:23  6.36  6.35 oracleodsbp
 2   ? 23047 patrol   154 20  3987M 52288K sleep 1306:05  6.31  6.29 oracleodsb
.................

这是台数据库服务器,工作负荷不算很重,load 值很低(<=0.40),总共有 341 个进程,其中与 oracle 相关的进程有 142 个,在 Memory 节有 5 个数字,反映的是实存使用量(real memory usage)、虚存使用量(virtual memory usage)和剩余自由内存量(the amount of free memory),前两个量都包含一个带括号的数据,表示的是活动(active)实存使用量或活动(active)虚存使用量,Eric Herberholz在 Memory Usage(What is using all of the memory?) 一文中对 active 的解释是特指可运行进程(runnable processes)。Memory 节的数字单位是页(1 页是 4096 字节),在 HP-UX 的 top 输出中,你没法知道系统配置的物理内存总量,而 AIX 和 Linux 的 top 输出中是可以看到这个数据的,你问我为什么?我也不知道,HP 完全可以把这个数据放到 top 中。获取系统物理内存总量值最简便的方法是看 syslog 文件,它不需要超级用户权限(dmesg 命令需要 root 权限)。

JHDB0100@oracle[/var/adm/syslog]pwd
/var/adm/syslog
JHDB0100@oracle[/var/adm/syslog]cat syslog.log | grep -i physical
Jul 23 20:34:25 JHDB0100 vmunix:     physical page size = 4096 bytes, logical page size = 4096 bytes
Jul 23 20:34:25 JHDB0100 vmunix:     Physical: 16775168 Kbytes, lockable: 12067576 Kbytes, available: 13882964 Kbytes
JHDB0100@oracle[/var/adm/syslog]

通过这个 syslog 文件,我们就知道这是一个 16GB 的系统,注意 available 内存数,physical 减去 available 得到的差额就是系统启动后内核代码(kernel code)及内核数据结构(kernel data structures)占用的内存量,我们的示例中内核使用了 2892204KB 内存。

top 输出中实存使用总量(total of used real memory)包括内核占用部分和全部用户进程占用部分,不包括共享内存部分,仍以前面数据为例,用 top 中实存占用总量 3823384KB,减去内核占用的 2892204KB, 用户进程大概占用 1GB 的内存空间,如何进行印证呢?一种方法是利用 top 输出中进程的 RES 字段值,RES 表示一个进程放到内存中的全部私有区(private regions)大小,私有区可能包括私有数据区、堆栈区,示例中的  oracle 进程有多个实例(呵呵,这里不是指数据库实例,指的是操作系统同名进程),其执行映像是共享的,不在私有区,利用 top -n 及 -f 选项得到全部进程的 RES 数据,全部加起来是 2GB,不要太在意数据的精确性,2GB 里面可能还是存在重复计算的问题;另一种方法是利用 ps 的 SZ 字段值,SZ 包括了放到内存中的执行映像、数据及堆栈空间,当系统中同一进程存在大量实例时(譬如类似 oracle 那样的进程),累加结果会非常离谱,可用如下命令计算全部进程的 SZ 和:

JHDB0100@oracle[/home/db/oracle]UNIX95=1 ps -eo sz,pid,args | sort -nr | awk '{ print $1 }' | awk '{ total += $1} END { print total }'

SZ 数字单位是页(4096字节),前面 341 个进程用 ps 算的结果是 16GB, 吓一跳吧,这数据还有没有意义啊,这里面重复统计的数量惊人,一个 oracle 进程的 SZ 值一般有 29000 页(即 110 MB),估计这里面只有 20MB 左右是私有的,其它都是共享的,16GB - (140 X 100MB)= 2GB(oracle 进程数是 140 个), 也与 top 计算的相当。这里我们都是用常规工具(ps、top 等)做些近似计算,借此我们对 top 中实存使用总量有点印象了,那么接下来要问的就是活动实存使用量怎么得来的?我们看到可运行进程(runnable processes)有 23 个,1165440KB 活动实存用量就是这 23 个活动进程所占用内存与活动内核代码所占用内存之和。

好了该谈谈 memory 节与虚存有关的两个数字了,即虚存使用总量和活动虚存用量,Unix/Linux 都通过虚存技术管理内存,这里不说虚存技术的好处了,先交代两点,一是虚存使用总量一定大于等于实存使用总量,活动虚存用量一定大于等于活动实存用量;二是虚存大于实存的那一部分不要认为就一定分配到了 swap 上,现代操作系统都有共享库动态加载机制,许多库文件在虚存上有空间定义,但未必放到了内存中,此外有些进程通过 malloc 分配了空间,但程序执行期间又没有用到它,它就只在虚存中存在。

活动虚存用量与 vmstat 输出中的 avm 值相当,可互相参照,看下面 vmstat 输出:

JHDB0100@oracle[/home/db/oracle]vmstat 3 3
         procs           memory                   page                              faults       cpu
    r     b     w      avm    free   re   at    pi   po    fr   de    sr     in     sy    cs  us sy id
    3     1     0   374018  946742  275    5     0    0     0    0     0   3088  54217  1761  30  3 66
    3     1     0   374018  946656   10    0     0    0     0    0     0   2549  45126  1210  26  2 72
    3     1     0   374018  946686   11    0     0    0     0    0     0   2529  46178  1222  25  2 73
JHDB0100@oracle[/home/db/oracle]

avm 字段数据单位是页(4KB)。avm 值与活动虚存用量大体相当,这实际上是一个经验观察的结果,虽然两者说的都是虚存的事,但定义上是有差别的,根据 EricHerberholz 的交代,活动虚存用量指的是可运行进程对内存的总需求量,不含睡眠或暂停的进程(Total memory for runnable processes, as opposed to sleeping or stoppedprocesses.),而 avm,[Sauers04] 中是这样描述的:avmstands for active virtual memory. It takes looking at the vmstat source code todetermine that avm is the sum of text, data, and stackpages in use for all processes, not including shared library or shared memorypages!

vmstat 中 avm 包括了全部进程的执行映像、数据区及堆栈区,但不包括共享库或共享内存部分。avm 不仅仅针对活动进程,睡眠进程或者暂停进程都在其统计范围内。这是个有趣的问题,top 的活动虚存用量与 vmstat 的 avm 来了个殊途同归,这个现象我也无法解释,因为我没有读 top 和 vmstat 的源码。

memory 节剩下的最后一项数据是自由内存量,示例中是 3702400KB, 这与 vmstat 的 free 字段是对应的。

有了上面关于 top 输出中 memory 部分稍微理性的知识,我们就能让 top 在内存分析方面发挥些作用。

我们来看看这个 16GB 的数据库服务器内存是如何使用的?

先看下交换空间使用情况

JHDB0100@oracle[/home/db/oracle]swapinfo -t
             Kb      Kb      Kb   PCT  START/      Kb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev     8388608       0 8388608    0%       0       -    1  /dev/vg00/lvol2
reserve       - 5960172 -5960172
memory  12091508 8622892 3468616   71%
total   20480116 14583064 5897052   71%       -       0    -

很好,没有使用交换空间。我们已经知道自由空间有 3.7GB 的样子,Cache 用了多少呢?Cache 在 top 及 vmstat 中都看不到,用下面的命令:

SADB3900@oracle[/home/db/oracle]sysdef | grep buf
bufpages                1258137          -          0-           Pages   -

bufpages 单位是页(4KB),算一下 Cache 用掉了 5GB 的空间,16GB - 3.7GB - 5GB = 7.3GB,剩下的 7.3GB 空间花在哪里?这是个 Oracle 数据库,执行以下命令:

JHDB0100@oracle[/home/db/oracle]sqlplus "/as sysdba"
.........
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

SQL> show sga

Total System Global Area 3875536896 bytes
Fixed Size                  2062952 bytes
Variable Size             436209048 bytes
Database Buffers         3422552064 bytes
Redo Buffers               14712832 bytes
SQL>

知道 SGA 用掉 3.8GB 的空间(共享内存部分),再剩下的就是 top 输出中显示的实存使用总量(3823384K),计算结果有点出入很正常,基本上都对上了。一个 16GB 的系统,如果有个 2GB、几 GB 的空间对不上,你可得好好查查。

我们再来看看 lunar 的那篇文章“一次异常内存消耗问题的诊断及解决”,这是一篇经典的内存性能分析文章,仔细阅读,确实颇有收获,不过我想做些补充。这是一台 16GB 的 RAC 数据库系统,操作系统是 HP-UX 11.11,通过 top 或者 vmstat 我们都能看到系统只剩 200MB 的自由内存了,但是 200MB 未必就不能工作,这要结合你的应用进行观察,在 vmstat 输出中我们看到 pi 值平均在 30 以上,re 值也超过 100,页活动非常频繁,pi 表示的是交换出去的页又被调回来;再看交换空间的使用情况(swapinfo),32GB 的交换空间(/dev/vg00/lvol2)中有 4GB 被用掉,不少啊,这样看,系统内存确实存在问题,top 中显示系统中有 966 个进程,其中活跃进程有 15 个,可能存在进程换进换出的问题,用户抱怨系统慢是有原因的。现在我们做点加减法,看是否存在内存丢失或使用异常的问题,这是个 Oracle 数据库服务器,SGA 用掉了 7.3GB, 自由内存有 200MB, 用 16GB 减去这两部分,还剩 8.5GB 空间,这 8.5 GB 空间会由内核代码与内核数据结构、全部进程的常驻内存段(含 text、data、stack)和文件系统 Cache 构成,根据 top ,我们发现实存使用总量有 14GB,太大了,900多个进程加内核占用不可能用到 14GB,14GB 还不含 Cache 和共享内存部分,说不定 SGA 的一部分都到了交换区上,lunar 文中未提到 Cache 值,因 Cache 是动态调整的,内存这么吃紧,估计 Cache 也挪作他用了,顶多剩下几十、上百兆。900多进程加内核顶多用到 7GB 左右,那还有 7GB 被谁用了,肯定不会是内核,可以用 ps 查查(看 SZ 字段)哪个进程用了上 GB 的内存,lunar 是通过 ipcs 和 shminfo 命令找到这个进程的,顺便说一下,用 ipcs 看到的那个异常的 6.2GB 的共享内存段是不正常的,它已经变成了私有内存段。