free(推荐使用)
- free提供的是系统整体使用内存的总体情况(最常用的命令),包括空闲内存量。
- 虽然free命令可能会显示一个特定系统没有多少空闲内存,但这并不一定是坏事。
- linux内核不会让空闲内存一直闲着,而且会将它作为高速缓存用于硬盘读,或者是作为缓冲区用于硬盘写。这可以显著提升系统性能。
- 由于这些高速缓存和缓冲区总是可以丢弃的,所以,当应用程序需要时这些内存还是可以使用的。free显示的是空闲内存容量加上或者减去这些缓冲区的容量
语法
与内存性能相关的选项:
free [-l] [-t] [-s delay] [-c count]
-s delay
:采样间隔-c count
:采样次数-l
:展示使用了多少高端内存和低端内存
与内存性能相关的输出项(其中的数值都默认以字节为单位):
Total
:物理内存和交换空间的总量(总内存⼤⼩)Used
:使用的物理内存和交换分区的容量(已使⽤内存的⼤⼩,包含了共享内存)Free
:未使用的物理内存和交换分区的容量(未使⽤内存的⼤⼩)Shared
:共享内存的⼤⼩buff/cache
: 缓存和缓冲区的⼤⼩;available
:新进程可⽤内存的⼤⼩(available不仅包含未使⽤内存,还包括了可回收的缓存,所以⼀般会⽐未使用内存更大。不过,并不是所有缓都可以回收,因为有些缓存可能正在使用中。)
free包含了所有重要的内存统计信息
实例
[root@localhost bin]# free
total used free shared buff/cache available
Mem: 7990288 2710200 3111592 23656 2168496 4894380
Swap: 6291452 0 6291452
[root@localhost bin]# free -t
total used free shared buff/cache available
Mem: 7990288 2710936 3110856 23656 2168496 4893644
Swap: 6291452 0 6291452
Total: 14281740 2710936 9402308
[root@localhost bin]# free -l
total used free shared buff/cache available
Mem: 7990288 2711252 3110548 23656 2168488 4893336
Low: 7990288 4879740 3110548
High: 0 0 0
Swap: 6291452 0 6291452
top(推荐使用)
- 默认情况下,top展示的是对进程的CPU消耗量降序排列的列表,但是它也可以调整为按内存使用总量排序,以便你跟踪哪个进程使用的内存最多
- 在找哪个进程的内存出问题之前,一般需要先top (M)看一下进程使用最低
语法
top不用任何特定命令行选项来控制其显示内存统计信息。它的调用命令行如下:
top
不过,一旦开始运行,top允许你显示系统级内存信息,还是显示按照内存使用量排序的进程:
m
:切换是否将内存使用量信息显示到屏幕M
:按照任务使用的内存量排序。由于分配给进程的内存量可能会大于其使用量,因此,该项按驻留集大小排序。驻留集大小是指进程实际使用量,而不是简单的进程使用量。
# 按下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 输出界⾯的顶端,也显示了系统整体的内存使⽤情况。然后是与内存性能相关的选项
%MEM
:进程使⽤物理内存占系统总内存的百分⽐。VTRT
:进程虚拟内存的大小,只要是进程申请过的内存,即使还没有真正分配物理内存,也会计算在内RES
:常驻内存的大小,也就是应用程序进程实际使用物理内存的大小,但不包括swap和共享内存SHR
:共享内存的大小,比如与其他进程共同使用的共享内存、加载到动态链接库以及程序的代码段等(单位为KB)SWAP
:进程使用的交换区(单位为KB)总量CODE
:进程的可执行代码使用的物理内存总量(单位为KB)DATA
:专门分配给进程数据和堆栈的内存总量(单位为KB)nDRT
:需要刷新到硬盘的脏页面的数量Mem:total,used、free
:对物理内存来说,该项表示的是其总量、使用量和空闲量swap:total、used、free
:对交换分区来说,该项表示的是其总量、使用量和空闲量active
:当前活跃的物理内存总量inactive
:非活跃而且一段时间内未被使用的物理内存总量buffers
:用于缓冲区写入硬盘的数值的物理内存总量(单位为KB)
除了要认识这些基本信息,在查看 top 输出时,你还要注意两点。
- 第⼀,虚拟内存通常并不会全部分配物理内存。从上⾯的输出,你可以发现每个进程的虚拟内存都⽐常驻内存⼤得多。
- 第⼆,共享内存 SHR 并不⼀定是共享的,⽐⽅说,程序的代码段、⾮共享的动态链接库,也都算在 SHR ⾥。当然,SHR 也包括了进程间真正共享的内存。所以在计算多个进程的内存使⽤时,不要把所有进程的 SHR 直接相加得出结果
vmstat
vmstat除了可以检测CPU性能统计信息外,还可以检测:
- 使用了多少交换分区
- 物理内存是如何被使用的
- 有多少空闲内存
vmstat有两种模式:采样模式和平均模式。
语法
与内存有关的命令行选项:
vmstat [-a] [-s] [-m]
-a
:改变内存统计信息的默认输出以表示活跃/非活跃内存量,而不是缓冲区和高速缓存使用情况的信息-s
:打印输出vm表。自系统启动开始的综合统计信息。该项木能用于采样模式,它包含了内存和CPU的统计数据-m
:输出内核分片信息。键入cat/proc/slabinfo
可以获得同样的信息。信息详细展示了内核内存是如何分配的,并有助于确定哪部分内核消耗内存最多
与内存有关的输出统计信息:
swap
:当前交换到硬盘的内存总量free
:未被操作系统或应用程序使用的物理内存总量buff
:- 系统缓冲区大小(单位为KB),或者用于存放等待保存到硬盘的数据的内存大小(单位为KB)。
- 该存储区允许应用程序向linux内核发出写调用后立即继续执行(而不是等待直到数据被提交到硬盘)
cache
:- 用于保存之前从硬盘读取的数据的系统高速缓存或者内存的大小(单位为KB)。
- 如果是应用程序再次需要该数据,内核可以从内存而非硬盘抓取数据,由此可以提高性能
active
:被使用的活跃内存量inactive
:不活跃的内存总量(单位为KB),或者一段时间未被使用,适合交换到硬盘的内存量si
:上一次采样中,从硬盘进来的内存交换速率(单位为KB/s)so
:上一次采样中,待硬盘去的内存交换速率(单位为KB/s)pages paged in
:从硬盘读入系统缓冲区的内存总量(单位为页)pages paged out
:从系统高速缓存写到硬盘的内存总量(单位为页)pages swapped in
:从交换分区读入系统内存的内存总量(单位为页)pages swapped out
:从系统内存写到交换分区的内存总量(单位为页)user swap
:linux内核目前使用的交换分区总量free swap
:当前可用的交换分区总量total swap
:系统的交换分区总量,等于used swap + free swap
- Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。
- LInux操作系统中有个swap硬盘分区,这个分区就是专门给Linux操作系统进行内存交换用的。
实例
下面显示了从系统启动开始的性能统计数据的均值(si、so),以及其他信息的瞬间值(swpd、free、buff、cache):
- 系统当前没有内存交换到硬盘(swpd),表示内存充足
- 有3306MB空闲内存(free)
- 大概2MB用于缓冲区(buff),以保存还未刷新到硬盘的数据
- 大概216MB用于硬盘缓存(cache),以保存过去从硬盘读取的数据
# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 3306324 2116 2163624 0 0 50 8 232 336 4 15 80 0 0
下面显示了活跃与非活跃页面的信息数量:
- 活跃内存大概2672MB
- 不活跃内存1457MB,非活跃内存表明了有多少内存可以交换到硬盘
vmstat -a
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free inact active si so bi bo in cs us sy id wa st
1 0 0 3308280 1457176 2672476 0 0 49 8 450 745 4 15 80 0 0
从下面可以看出这个系统内存数据交换频繁。(vmstat 1 100
,采样100次,每隔1s采样一次)
- si列显示了每个采样期间,数据的读交换率分布为480KB、832KB、764KB、512KB
- so列显示了每个采用期间,内存数据的写交换率分布为9KB、0KB、916KB、0KB、1068KB、444KB、792KB
这些结果就可以说明当前系统没有足够的内存来处理所有的运行进程。
- 当一个进程的内存被保存下来,以便为之前已经交换到硬盘的应用程序腾位置时,就会出现高频率的换入和换出
- 如果有两个运行程序需要的内存量都超过了系统可提供的量,后果会很糟糕。比如
- 两个进程都在使用大量的内存,且它们都试图同时运行,而且每个进程都可以导致另一个的内存被写交换
- 当一个程序需要一块内存时,它会把另一个程序需要的一块内存踢出去。
- 而当另一个应用程序开始运行时,它又会把第一个程序正在使用的一块内存踢出去,并等待自己的内存交换分区加载进来
- 这可能会导致两个应用程序出现停顿,以等待他们的内存从交换分区中取回,然后才能继续执行
- 只要一个程序进步一点点,它就会将另一个进程使用的内存交换出去,从而导致这个程序慢下来。这种情况叫做颠簸
- 发生颠簸时,系统会花费大量的时间将内存读出或者写入交换分区,系统性能就会急剧下降
从下图可以看出,交换最终停止了,最有可能的原因是交换到硬盘的内存不是第一个进程立即需要的。这就意味着交换是有效的,不是正在使用的内存内容被写入到硬盘,然后内存就会分配给需要它的进程
从下面例子可以看出:
- total memory:系统总共有7990-288KB内存
- swap swap:系统大概有有1263-xxxKB交换分区
- pages paged in:从硬盘读入的页面总数。这个统计信息包括启用应用程序读取的页面,以及该应用程序可以使用的页面
从下面例子可以看出linux内核是如何分配其内存的:
- linux内核有一系列“分片”来保存其动态数据结构
- vmstat显示每一个分片(cache),展示使用了多少元素(Num)、分配了多少(Total)、每个元素的大小(Size)、整个分配使用了多少内存页(Pages)。这些信息有助于跟踪内核究竟是怎么使用其内存的
slabtop
- slabtop与to相似,但是它并不显示系统中进程的CPU和内存使用情况的信息,slabtop实时显示内核是如何分配各种缓存的,以及这些缓存的被占用情况
- 在内部,内核有一系列的缓存,它们由一个或者多个分片(slab)构成。每个分配包括一组对象,对象个数为一个或者多个。这些对象可以是活跃的或者非活跃的。
- slab展示的是不同分片的状况,它显示了这些分片的被占用的情况,以及它们使用了多少内存
语法
内存相关的命令行选项:
slabtop [--delay n --sort={a | b | c | l | v | n | o | p | s | u}]
--delay n
:采用周期--sort a
:按每个分片所包含的活跃对象数排序--sort b
:按特定缓存中的每个分片所包含的全部对象(活跃的和非活跃的)数量排序--sort c
:按照每个缓存所用的内存总量排序--sort l
:按照每个缓存使用的分片数排序--sort v
:按照每个缓存使用的活跃分片数排序--sort n
:按照缓存名称排序--sort o
:按照特定缓存中的对象数量排序--sort p
:按照每个分片使用的页数排序--sort s
:按照缓存中对象的大小排序
slabtop可以一窥linux内核的数据结构
实例
默认情况下,slabtop会填满增高控制台,而且每3s就更新一次统计数据
由于slabtop提供的信息是周期性更新的,因此它是观察linux内核的内存使用情况随工作负载变化的一种很好的方法
sar
sar的优势在于,它提供一些重要数值的变化率,你可以通过这些数值查看内存使用情况究竟是如何随时间变化的,而不用去找出这些值在样本之间的差异。
语法
默认情况下,sa显示的是CPU性能统计数据。与内存性能相关的命令行选项如下:
sar [-B] [-r] [-R]
-B
:报告的信息为内核与磁盘之间交换的数据。此外,对于v2.5之后的内核版本,显示为缺页数量-W
:报告的是系统交换的页数-r
:报告系统使用的内存信息。它包括总的空闲内存、正在使用的交换内存、缓存和缓冲区的信息
sar与内存统计信息相关的输出:
kbmemfree
:当前空闲或者未被使用的物理内存总量(以KB为单位)kbmemused
:当前被使用的物理内存总量(以KB为单位)%memused
:被使用的物理内存总量所占的百分比kbbuffers
:用作磁盘写缓冲区的物理内存总量kbcached
:用作磁盘读缓存的物理内存总量frmpg/s
:系统释放内存页面的速率。如果数值为负,则表示系统正在分配它们bufpg/s
:系统将新内存页面用作缓存的速率。如果数值为负,则表示缓冲数量正在减少,系统对它们的使用量也在减少pgpgin/s
:内核以分页形式每秒从磁盘换入的内存总量(以KB为单位)pgpgout/s
:内存以分页形式每秒换出到磁盘的内存总量(以KB为单位)fault/s
:每秒内存子系统需要满足的缺页总数。这些缺页不一定需要访问磁盘majflt/s
:每秒内存子系统需要满足的缺页总数,这些缺页需要访问磁盘
实例
运行sar -r 1 5
,输出如下,显示了sar提供的关于当前内存子系统整体的信息:
- 在观察期间,空闲内存量从2252MB增加到2253MB,已经使用的内存量从5737MB上升到5736BM
- 系统使用的内存量占整个内存容量的比例变化范围为71.81%到71.79%
运行sar -R 1 5
,输出如下:
- 在第一个样本期间,系统使用空闲内存的速率约为每秒82个页面。 然后系统释放了大于16个页面,接着又使用了大约20个页面
- 观察期间只有一次缓存页面数是增加的,速率为每秒2.02个页面
- 最后,缓存页面减少了2.02,不过最终,它们增加的速率为每秒64.39个页面
运行sar -B 1 5
,输出如下:
- 在第三个样本期间,系统从内存写了大约20个页面到磁盘
- 该系统的缺页数相对较高,这就意味着内存页面在被分配和使用。幸运的是,这些都不是主缺页,系统不必为了解决它们而去访问磁盘
/proc/meminfo
- linux内核提供用户可读的文本文件/proc/meminfo来显示当前系统范围内的内存性能统计信息,它提供了系统范围内内存统计数据的超集,包括了vmstat、top、free、procinfo等的信息
- 如果你想要定期更新,就需要自己写一个脚本或者一些信息来实现这个功能
- 如果你想要保存内存性能信息或者是将其与CPU统计信息向协调,就必须创建一个新的工具或者写一个脚本
语法
cat /proc/meminfo
一些与内存统计相关的输出:
- MemTotal:系统物理内存总量
MemFree
:空闲物理内存总量Buffers
:等待中的磁盘写操作的内存总量Cached
:用于缓存磁盘读操作的内存总量SwapCached
:在交换分区和物理内存中都存在的内存总量Active
:系统中当前处于活跃状态的内存总量Inactive
:系统中当前处于非活跃状态而且可用于交换的内存容量HighTotal
:高端内存容量(以KB为单位)HighFree
:空闲的高端内存容量(以KB为单位)- `LowTotal``:低端内存容量(以KB为单位)
LowFree
:空闲的低端内存容量(以KB为单位)SwapTotal
:交换内存容量(以KB为单位)SwapFree
:空闲的交换内存容量(以KB为单位)Dirty
:当前系统有多少KB的内存等待写入磁盘内存Writeback
:等待被写入磁盘的内存Mapped
:用mmap映射到一个进程虚拟地址空间的内存容量Slab
:内核分片内存的总量(以KB为单位)PageTables
:为内核页表保留的内存容量Committed_AS
:所需内存容量,在当前的工作负载下,这个容量几乎是不会被耗尽的。通常情况下,内核会分配更多的内存,预取应用程序会超分配。如果所有的应用程序都使用自己被分配的内存,那么这个就是你需要的物理内存容量VmallocTotal
:vmalloc可用的内核内存容量VmallocUsed
:vmalloc已经使用的内核内存容量VmallocChunk
:vmalloc可用内存的最大的连续块
实例
其他工具
- procinfo
- gnome-system-monitor
其他
哪些进程被 OOM 杀死了
$ dmesg | grep -i "Out of memory"
Out of memory: Kill process 9329 (java) score 321 or sacrifice child
怎么评估应用程序的最小内存
- 要确定⼀个进程或者容器的最⼩内存,最简单的⽅法就是让它运⾏起来,再通过 ps 或者 smap ,查看它的内存使⽤情况。
- 不过要注意,进程刚启动时,可能还没开始处理实际业务,⼀旦开始处理实际业务,就会占⽤更多内存。所以,要记得给内存留⼀定的余量。