本节我们来介绍内存相关的监测工具。
1. 命令总览
下面的图片摘录自极客时间专栏-Linux性能优化实战,分别从下面 3 个方面总结了内存相关的性能检测工具:
- 从内存的性能指标出发,根据指标找工具
- 从工具出发,根据工具找指标
- 根据工具指标之间的内在联系,掌握内存分析的套路
有些工具是通用的分析工具,后面会在单独的章节中详细说明他们的使用。本节会介绍如下内存专用的分析工具的使用
Linux |
Solaris |
作用 |
说明 |
vmstat |
vmstat |
虚拟和物理内存统计信息 |
|
slabtop |
::kmastat |
内核块分配统计信息 |
|
pmap |
pmap |
进程地址空间统计信息 |
|
pcstat |
pcstat |
查看文件在内存中的缓存大小以及缓存比例 |
|
cachetop |
cachetop |
实时查看间隔时间内每个进程的缓存命中情况 |
bcc工具包中 |
cachestat |
cachestat |
查看整个操作系统缓存的读写命中情况 |
bcc工具包中 |
memleak |
memleak |
内存泄漏跟踪 |
bcc工具包中 |
ps |
ps |
进程状态 |
通用命令,位于独立的一节中 |
top |
prstat |
监控进程内存使用 |
通用命令,位于独立的一节中 |
sar |
sar |
内存,swap使用统计信息 |
通用命令,位于独立的一节中 |
Systemtap |
Dtrace |
动态追踪 |
通用命令,位于独立的一节中 |
除此之外,还包括以下内容:
- 内存调优
2. 内存统计命令
2.1 vmstat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
> vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 1077816 2116 620312 0 0 65 43 34 53 0 0 99 0 0
# 说明:
# 除了 r 列外,第一行是系统启动以来的总结信息
> 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
2 0 0 342188 472012 815924 0 0 68 84 160 72 9 1 90 0 0
> vmstat -s
1882152 K total memory
250252 K used memory
815892 K active memory
472012 K inactive memory
341924 K free memory
172 K buffer memory
1289804 K swap cache
2097148 K total swap
0 K used swap
2097148 K free swap
99051 non-nice user cpu ticks
0 nice user cpu ticks
12143 system cpu ticks
998690 idle cpu ticks
360 IO-wait cpu ticks
0 IRQ cpu ticks
358 softirq cpu ticks
0 stolen cpu ticks
758858 pages paged in
934798 pages paged out
0 pages swapped in
0 pages swapped out
1777012 interrupts
803881 CPU context switches
1586602557 boot time
31172 forks
|
vmstat [t [n]]
- 作用: 虚拟内存统计命令
- 参数:
- -t:采样间隔
- -n:采样次数,可选,默认值是1
- -S: -Sm 以MB 为单位显示结果
- -a: 输出非活动和活动页缓存的明细
- -s: 以列表显示内存统计信息
- 输出:
- r: 可运行线程数,所有等待加上正在运行的线程数,不包括处于不可中断睡眠状态的线程
- cpu:
- 系统全局范围内的平均负载
- 第一行统计的系统启动以来的平均负载 – 新版本可能不会显示
- 其余行统计的是时间间隔周期内的平均负载
- memory:
- swpd: 交换出的内存量
- free: 空闲可用内存
- buff: 用于缓冲缓存的内存
- cache: 用于页缓存的内存
- swap:
2.2 slabtop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
> sudo slabtop -sc
Active / Total Objects (% used) : 1079865 / 1085229 (99.5%) # slab 管理的对象数量
Active / Total Slabs (% used) : 27647 / 27647 (100.0%) # Slab 数量
Active / Total Caches (% used) : 69 / 97 (71.1%) # 缓存的 slab 数量
Active / Total Size (% used) : 151423.96K / 153971.68K (98.3%) # slab 管理的内存大小
Minimum / Average / Maximum Object : 0.01K / 0.14K / 8.00K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
50440 50440 100% 0.94K 6305 8 50440K xfs_inode
81879 81087 99% 0.19K 3899 21 15596K dentry
15392 15266 99% 1.00K 1924 8 15392K kmalloc-1024
139737 139737 100% 0.10K 3583 39 14332K buffer_head
16419 16419 100% 0.58K 1263 13 10104K inode_cache
17262 17262 100% 0.57K 1233 14 9864K radix_tree_node
|
slabtop:
- 作用: 内核内存信息统计,等同于 vmstat -m
- 来源: slab 统计信息来自 /proc/slabinfo
- 参数
- -d n:每n秒更新一次显示的信息,默认是每3秒;
- -s S:指定排序标准进行排序;
- -o:显示一次后退出
- -V:显示版本
2.3 pmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
> sudo pmap -x 792|head
792: /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid
Address Kbytes RSS Dirty Mode Mapping
0000000000400000 4 4 0 r-x-- python2.7
0000000000600000 4 4 4 r---- python2.7
0000000000601000 4 4 4 rw--- python2.7
00000000017b4000 8800 8684 8684 rw--- [ anon ]
....
> sudo pmap -d 792 |head
792: /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid
Address Kbytes Mode Offset Device Mapping
0000000000400000 4 r-x-- 0000000000000000 0fd:00000 python2.7
0000000000600000 4 r---- 0000000000000000 0fd:00000 python2.7
0000000000601000 4 rw--- 0000000000001000 0fd:00000 python2.7
00000000017b4000 8800 rw--- 0000000000000000 000:00000 [ anon ]
00007fa0ac000000 132 rw--- 0000000000000000 000:00000 [ anon ]
.....
mapped: 359028K writeable/private: 30856K shared: 36K
|
pmap PID
- 作用: 列出进程的内存映射,显示它们的大小,权限和映射对象
- 参数:
- -x:显示扩展格式;
- -d:显示设备格式;
- -q:不显示头尾行;
- -V:显示指定版本
- 输出:
- pid -X
- Address: 映射的起始地址
- Kbytes: 虚拟内存大小
- RSS: 主存大小
- Dirty: 脏页大小
- Mode: 映像权限: r=read, w=write, x=execute, s=shared, p=private (copy on write)
- Mapping: 映像的文件,[anon]为已分配内存 [stack]为程序堆栈
- pid -d
- Offset: 文件偏移
- Device: 设备名
- mapped: 进程映射的虚拟地址空间大小,也就是该进程预先分配的虚拟内存大小,即ps出的vsz
- writeable/private: 进程所占用的私有地址空间大小,也就是该进程实际使用的内存大小
- shared: 表示进程和其他进程共享的内存大小
2.4 pcstat
pcstat 是一个基于 Go 语言开发的工具,所以安装它之前,首先需要安装 Go 语言。由于不可描述的原因,go 包的安装可能会遇到问题,建议像下面这样设置一下代理后在安装:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# go 安装
cd /usr/local
wget https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.14.4.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/go.sh
# 设置代理 https://goproxy.io/zh/
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
# 安装 pcstat
go get golang.org/x/sys/unix
go get github.com/tobert/pcstat/pcstat
|
pcstat
- 作用: 查看文件在内存中的缓存大小以及缓存比例
- 参数:
1
2
3
4
5
6
|
$ pcstat /bin/ls
+---------+----------------+------------+-----------+---------+
| Name | Size (bytes) | Pages | Cached | Percent |
|---------+----------------+------------+-----------+---------|
| /bin/ls | 133792 | 33 | 0 | 000.000 |
+---------+----------------+------------+-----------+---------+
|
指标含义:
- Cached: /bin/ls 在缓存中的大小
- Percent: 缓存的百分比
2.5 smem
2.6 其他命令
命令 |
作用 |
dmesg |
检查 OOM |
valgrind |
包含一个 memcheck 性能分析套件,可用于发现泄漏, 会有严重的系统开销 |
swapon |
添加和观察swap分区 |
iostat |
如果 swap 是物理磁盘或块,可用此命令观测系统是否在换页 |
/proc/zoneinfo |
内存区域 NUMA 节点的统计信息 NUMA 非均匀访存模型 |
/proc/buddyinfo |
内核页面伙伴分配器统计信息 伙伴分配器:Linux 的页面分配器 |
3. 内存调优
最重要的内存调优是保证应用程序保留在主存中,并且避免换页和交换经常发生。
3.1 可调参数
Documention/sysctl/vm.txt 的内核源码文档介绍了多种内存可调参数。常用示例如下
参数 |
默认值 |
作用 |
vm.dirty_background_ratio |
10 |
触发pdflush后台回写的脏页百分比 |
vm.dirty_ratio |
20 |
触发一个写入进程开始回写脏页比例 |
vm.dirty_expire_centisecs |
3000 |
使用pdflush的脏存储器最小时间 |
vm.dirty_writeback_centisecs |
5000 |
pdflush 活跃时间间隔,0为停用 |
vm.min_free_kbytes |
dynamic |
设置期望的空闲内存大小,dynamic为系统自动设置 |
vm.overcommit_memory |
0 |
0: 利用探索算法允许合理的过度使用 1: 一致过度使用 3: 不允许过度使用
|
vm.swappiness |
60 |
相对于页面高速缓存回收更倾向于用交换释放内存的程度 高数值更倾向于交换应用程序而保留页缓存 |
3.2 配置大页面
更大的页面能通过提高 TLB 缓存命令率,来提升内存 IO 性能。现在处理器支持多个页面大小。设置大页面(巨页面)参考文档hugetlbpage.txt。关于大页面的使用详见文档
3.3 分配器
应用程序的用户级分配器可以在编译阶段选择,也可以在执行时用 LD_PRELOAD 环境变量设置。
3.4 资源控制
主存限制和虚拟内存限制,可通过 ulimit 实现。Linux cgroup 内存子系统可提供多种附加控制:
- memory.memsw.limit_in_bytes: 允许的最大内存和交换空间
- memory.limit_in_bytes: 允许的最大用户内存,包括文件缓存
- memory.swappiness: 类似 vm.swappiness,作用于 cgroups
- memory.oom_control: 设置为 0,允许 OOM 应用于此 cgroup,1 不允许