free


内存监控命令free free命令输出中显示了系统的各种内存状态,具体包括物理内存和swap,物理内存中又分为已使用内存(used)、空闲内存(free)、共享内存(shared)、系统缓存(buff/cache)和目前可用内存(available)。 看下面一个输出:(它只能显示某一时刻的内存状态,不能做到实时的去显示)

linux 内存性能评估工具 free/smem_共享内存

在Mem这行的输出中,其实是有个等式关系的: Used+free+buff/cache=total   avaliable=buff/cache - shared,别看占用很多,当物理内存不够用的时候,这部分资源是可以马上释放掉的,释放掉供给free这一列去使用。

buff/cache这一部分其实是可以留给应用程序去使用的。

这里尤其注意一下,最后一列的可用内存 available。available不仅包含未使用内存,还包括了可回收的缓存,所以一般会比未使用内存更大。不过,并不是所有缓存都可以回收,因为有些缓存可能正在使用中。

一般有这样一个经验公式:available内存 >70%时,表示系统内存资源非常充足,不影响系统性能,available内存< 20%时,表示系统内存资源紧缺,需要增加系统内存,20%< available内存 < 70%时,表示系统内存资源基本能满足应用需求,暂时不影响系统性能。

对于free命令的解读就是看最后一列 available,这一列的值就是系统可以用的物理内存,如果这个值非常的小,那么要考虑内存资源是不是不够了,是不是需要增加内存。

最后我们还要关注swap使用的大小,正常来说swap不会使用的很大,如果使用很大,那么可能是物理内存不够用了。

swap是不是使用了就内存不足了,其实不是,就是在物理内存充足的情况下,swap也是可能会被使用的,当一个要使用很大内存的应用程序,在机器上面跑了一下,跑了之后将内存完全释放了,在跑的时候,内存不够了,系统会将一部分不经常使用的数据把它放到swap上面,当占用很大内存的进程跑完之后物理内存也释放了,之前转到swap里面的一部分数据永久的存在这里面了,不会再把它释放掉,所以最后可以看到物理内存还有很多,swap也被使用了。这种情况是正常的,只要不是使用的特别多。

smem


内存状态监测工具smem命令 Smem 是一款命令行下的内存使用情况报告工具,它能够给用户提供 Linux 系统下的内存使用的多种报告。和其它传统的内存报告工具不同的是,它有个独特的功能,可以报告PSS。

使用它的最大好处就是它可以统计出系统当中每一个进程使用的内存多少,free看到的是全局的内存使用。在调优的时候我想知道哪个进程占用了很多内存,我想kill掉等等,你单纯靠free命令是找不到的,这个时候通过smem这个命令它就能够发现哪个进程占用了很大的内存资源。

  • RSS(Resident set size),使用top命令可以查询到,是最常用的内存指标,表示进程占用的物理内存大小。但是,将各进程的RSS值相加,通常会超出整个系统的内存消耗,这是因为RSS中包含了各进程间共享的内存。
  • PSS(Proportional set size)所有使用某共享库的程序均分该共享库占用的内存时。显然所有进程的PSS之和就是系统的内存使用量。它会更准确一些,它将共享内存的大小进行平均后,再分摊到各进程上去。(看pss更加准确)
  • USS(Unique set size )进程独自占用的内存,它只计算了进程独自占用的内存大小,不包含任何共享的部分。

最准确的查看某个进程占用内存大小就使用pss,smem这个命令就可以精确的报告每个进程占用的内存有多少。pss其实是最精确的,统计进程占用的资源有多少。

smem默认按照从小到大的顺序去排序的。

看下面例子:

linux 内存性能评估工具 free/smem_数据_02

上图中,“-k”参数用来显示内存单位,“-s”是排序,uss是对uss列进行排序,这样,输出了系统中所有进程占用内存大小。 

如果要按照百分比显示可以使用 -p。

[root@localhost ~]# smem -p -s pss
PID User Command Swap USS PSS RSS
876 root /sbin/agetty --noclear tty1 0.00% 0.02% 0.02% 0.08%
740 root /usr/lib/systemd/systemd-ud 0.00% 0.25% 0.31% 0.52%
1 root /usr/lib/systemd/systemd -- 0.00% 0.41% 0.47% 0.68%
932 root /usr/sbin/NetworkManager -- 0.00% 0.43% 0.52% 0.81%
12966 root python /usr/bin/smem -p -s 0.00% 0.56% 0.60% 0.77%
1456 root /usr/bin/python -Es /usr/sb 0.00% 1.08% 1.23% 1.64%
957 polkitd /usr/lib/polkit-1/polkitd - 0.00% 1.17% 1.24% 1.49%
863 root /usr/bin/python -Es /usr/sb 0.00% 1.73% 1.90% 2.32%
1463 root /usr/bin/containerd 0.00% 3.87% 3.87% 3.91%
1807 root /usr/bin/dockerd -H fd:// - 0.00% 7.17% 7.18% 7.29%

也可以按照用户使用-u去统计,每个用户占用的内存情况

[root@localhost ~]# smem -u -k 
User Count Swap USS PSS RSS
chrony 1 0 684.0K 745.0K 1.6M
dbus 1 0 884.0K 977.0K 1.9M
postfix 2 0 2.4M 3.3M 7.7M
polkitd 1 0 11.4M 12.2M 14.6M
root 21 0 164.6M 173.8M 208.7M

 查看某个进程的情况     -P 进程名称

[root@localhost ~]# smem  -k -P docker
PID User Command Swap USS PSS RSS
12971 root python /usr/bin/smem -k -P 0 4.7M 5.1M 6.8M
1807 root /usr/bin/dockerd -H fd:// - 0 70.1M 70.2M 71.2M

可以看到smem功能还是非常强大的,它可以以多种方式去查看某个进程占用的内存有多少,还可以对占用内存排序,百分比的形式展示。 

 

 

 

补充


不过,我们知道,free显示的是整个系统的内存使用情况。如果你想查看进程的内存使用情况,可以用 top或者 ps等工具。比如,下面是 top的输出示例∶

# 按下M切换到内存排序
$ top
...
KiB Mem : 8169348 total, 6871440 free, 267096 used, 1030812 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7607492 avail Mem


PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
430 root 19 -1 122360 35588 23748 S 0.0 0.4 0:32.17 systemd-journal
1075 root 20 0 771860 22744 11368 S 0.0 0.3 0:38.89 snapd
1048 root 20 0 170904 17292 9488 S 0.0 0.2 0:00.24 networkd-dispat
1 root 20 0 78020 9156 6644 S 0.0 0.1 0:22.92 systemd
12376 azure 20 0 76632 7456 6420 S 0.0 0.1 0:00.01 systemd
12374 root 20 0 107984 7312 6304 S 0.0 0.1 0:00.00 sshd
...

top输出界面的顶端,也显示了系统整体的内存使用情况,这些数据跟free类似,我就不再重复解释。我们接着看下面的内容,跟内存相关的几列数据,比如 VIRT、RES、SHR 以及%MEM等。

这些数据,包含了进程最重要的几个内存使用情况,我们挨个来看。

VIRT:VIRT是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。

1、进程“需要的”虚拟内存大小,包括进程使用的库、代码、数据,以及malloc、new分配的堆空间和分配的栈空间等;
2、假如进程新申请10MB的内存,但实际只使用了1MB,那么它会增长10MB,而不是实际的1MB使用量。
3、VIRT = SWAP + RES

RES: RES是常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括Swap和共享内存。

1、进程当前使用的内存大小,包括使用中的malloc、new分配的堆空间和分配的栈空间,但不包括swap out量;
2、包含其他进程的共享;
3、如果申请10MB的内存,实际使用1MB,它只增长1MB,与VIRT相反;
4、关于库占用内存的情况,它只统计加载的库文件所占内存大小。
5、RES = CODE + DATA

SHR:SHR 是共享内存的大小,比如与其他进程共同使用的共享内存加载的动态链接库以及程序的代码段等。

1、除了自身进程的共享内存,也包括其他进程的共享内存;
2、虽然进程只使用了几个共享库的函数,但它包含了整个共享库的大小;
3、计算某个进程所占的物理内存大小公式:RES – SHR;
4、swap out后,它将会降下来。

%MEM:是进程使用物理内存占系统总内存的百分比。除了要认识这些基本信息,在查看 top输出时,你还要注意两点。

第一,虚拟内存通常并不会全部分配物理内存。从上面的输出,你可以发现每个进程的虚拟内存都比常驻内存大得多。

第二,共享内存SHR 并不一定是共享的,比方说,程序的代码段、非共享的动态链接库,也都算在SHR里。当然,SHR也包括了进程间真正共享的内存。所以在计算多个进程的内存使用时,不要把所有进程的 SHR 直接相加得出结果。