目录
Swap原理
NUMA和swap
swappiness
创建swap
一个swap的例子
参考
内存不足的情况
1.内存回收
2.OOM杀死进程
内存紧张导致的OOM,是指系统杀死占用大量内存的进程,释放这些内存,再分配给其他更需要的进程
内存回收,就是系统释放掉可以回收的内存,比如cache和buffer,就是属于可回收内存,他们在内存管理中,通常叫 文件页(File-backed Page)
大部分文件页,都可以直接回收,以后有需要再从磁盘重新读取就可以了,而那些被应用程序修改过,暂时还没有写入磁盘的数据(脏页),就需要先写入磁盘,才能再进行内存释放
脏页的写入方式包括
1.在应用程序中,调用fsync,把脏页同步到磁盘中
2.也可以交给系统,由内核线程pdflush负责将这些脏页刷新
除了buffer和cache,通过内存映射获取的文件映射页,也可以被释放掉,下次再访问的时候,从文件中重新读取就可以了
应用程序动态分配的堆内存,也就是内存管理中的 匿名页(Anonymous Page),这些不能直接回收
Linux是通过swap机制,将这些匿名页中的内存先写到磁盘中,再释放掉这些内存,给其他更需要的进程使用,再访问这些内存时,重新从磁盘读取内存就可以了
其原理是把一块磁盘空间或者一个本地文件,当内存来使用
1.换出,就是把进程暂时不用的内存数据存储到磁盘中,并释放掉这些数据占用的内存
2.换如,进程再次访问这些内存的时候,把他们从磁盘读到内存中来
swap其实是把系统的可用内存变大了,即使服务器的内存不足时,也可以运行大内存的应用程序
即使现在内存便宜了也大了,但是再大的内存也有不够用的时候
比如当内存不足时,有些应用程序并不想被OOM杀死,而是希望能缓一段时间,等待人工介入,或者等系统自动释
放其他进程的内存,再分配给他
笔记本的快速开机和休眠,就是基于swap,休眠时把系统的内存存入磁盘,等再次开机时就从磁盘中加载内存,
省去了很多应用初始化的过程,加速了开机速度
Linux什么时候回收内存呢?
比如有新的大块内存分配请求时,剩余内存不足,这时候系统就需要回收一部分内存(比如cache和buffer_,尽可
能的蛮族新内存请求,这个过程通常被称为 直接内存回收
除了直接内存回收,还有一个专门的内核线程用来定期回收内存,也就是 kswapd0,为了衡量内存的使用情况,
kswapd0定义了三个内存阈值(watermark 也称水位),分别是
页最小阈值(pages_min),页低阈值(pages_low),页高阈值(pages_high),剩余内存,则使用pages_free表示
kswap0定期扫描内存使用情况,并根据剩余内存落在这三个阈值的空间位置,进行内存回收操作
1.剩余内存小于 页最小阈值,说明进程可用内存都耗尽了,只有内存才可以分配内存
2.剩余内存落在 页最小阈值 和 页低阈值中间,说明内存压力比较大,剩余内存不多了,kswapd0会执行内存
回收,直到剩余内存大于高阈值为止
3.剩余内存落在 页低阈值 和页高阈值中间,说明内存有一定压力,但还可以满足新内存请求
4.剩余内存大于 页高阈值,说明剩余内存比较多,没有哦内存压力
一旦剩余内存小雨页低阈值,就会触发内存的回收,这个页低阈值,可以通过内核选项
/proc/sys/vm/min_free_kbytes
来设置,而其他两个值,都是根据页低阈值,直接计算生成的
page_low = pages_min * 5/4
pages_high = pages_min * 3/2
有时候系统的剩余内存还很多,但还是发生了swap
这是因为处理器的NUMA(Non-Uniform Memory Access)架构导致的
在NUMA架构下,多个处理器被划分到不同Node上,且每个Node都拥有自己的本地内存空间
而同一个Node内部的内存空间,实际上又可以进一步分为不同的内存域(Znode),比如直接内存访问区(DMA),普通内存区(NORMAL),伪内存区(MOVABLE)等,如下图所示
通过numactl命令,可以查看处理器在Node的分布情况,以及每个Node的内存使用情况
numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38
node 0 size: 65442 MB
node 0 free: 16721 MB
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
node 1 size: 65536 MB
node 1 free: 30760 MB
node distances:
node 0 1
0: 10 21
1: 21 10
通过 cat /proc/znoeinfo 查看信息
Node 0, zone DMA
pages free 3933
min 2
low 2
high 3
scanned 0
spanned 4095
present 3835
nr_free_pages 3933
nr_inactive_anon 0
nr_active_anon 0
nr_inactive_file 0
nr_active_file 0
nr_unevictable 0
nr_mlock 0
nr_anon_pages 0
nr_mapped 0
nr_file_pages 0
nr_dirty 0
nr_writeback 0
nr_slab_reclaimable 0
nr_slab_unreclaimable 0
nr_page_table_pages 0
nr_kernel_stack 0
nr_unstable 0
nr_bounce 0
nr_vmscan_write 0
nr_writeback_temp 0
nr_isolated_anon 0
nr_isolated_file 0
nr_shmem 0
numa_hit 0
numa_miss 0
numa_foreign 0
numa_interleave 0
numa_local 0
numa_other 0
nr_anon_transparent_hugepages 0
protection: (0, 1882, 64502, 64502)
pagesets
cpu: 0
count: 0
high: 0
batch: 1
vm stats threshold: 12
cpu: 1
。。。
比较重要的指标有
pages处的min,low,high,就是上面提到的三个内存阈值,free是剩余内存页数,跟后面的nr_free_pages相同
nr_zone_active_anon和nr_zone_inactive_anon,分别是活跃和非活跃的匿名页数
nr_zone_active_file和nr_zone_inactive_file,分别是活跃和非活跃的文件页
如果此时的剩余内存大于页高阈值,kswapd0就不会回收内存
如果某个Node内存不足,系统可以从其他Node寻找空闲内存,也可以从本地内存中回收内存,具体用哪种模式,通过下面参数来调整
/proc/sys/vm/zone_reclaim_mode
支持以下几个选项
默认的0,就是刚刚提到的模式,可以从其他Node寻找空闲内存,也可以从本地回收内存
1,2,4都表示只回收本地内存,2表示可以回写脏数据回收内存,4表示可以用Swap方式回收内存
内存回收机制,即包括了文件页,也包括了匿名页
1.对于文件的回收,就是直接回收缓存,或者把脏页写回到磁盘再回收
2.对于匿名页,就是通过swap机制,把他们写入到磁盘后再释放内存
Linux系统提供了下面这个参数,可以用来调整使用swap的积极程度
/proc/sys/vm/swappiness
swappiness的范围是0-100,数值越大,越积极使用swap,也就是更倾向于回收匿名页
数值越小,越消极使用swap,也就是更倾向于回收文件页
swappiness的范围是0-100,但并不是内存的百分比,而是调整swap积极度的权重,即使把他设置成0,还是可会发生swap
输入 free
free
total used free shared buff/cache available
Mem: 4039480 70100 3000168 2788 969212 3737268
Swap: 0 0 0
Swap大小为0,说明没有配置Swap
Linux支持两种类型的Swap,Swap分区 和 Swap文件
下面是配置Swap文件的列子
fallocate -l 8G /mnt/swapfile
file /mnt/swapfile
chmod 700 /mnt/swapfile
mkswap /mnt/swapfile
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
no label, UUID=92e57c51-23e6-4976-acc4-e0745c870bb7
swapon /mnt/swapfile
file swapfile
swapfile: Linux/i386 swap file (new style), version 1 (4K pages), size 2097151 pages, no label, UUID=92e57c51-23e6-4976-acc4-e0745c870bb7
再输入free
total used free shared buff/cache available
Mem: 4039480 72720 2996780 2788 969980 3734636
Swap: 8388604 0 8388604
swapoff -a #停止所有的swap分区
通过cat查看
cat /proc/swaps
Filename Type Size Used Priority
/mnt/swapfile file 2097148 0 -2
当设置swappiness为0的时候
cat /proc/sys/vm/swappiness
0
sar的swap和内存相关的man结果
#内存使用情况
-r Report memory utilization statistics. The following values are displayed:
kbmemfree
Amount of free memory available in kilobytes.
kbmemused
Amount of used memory in kilobytes. This does not take into account memory used by the kernel itself.
%memused
Percentage of used memory.
kbbuffers
Amount of memory used as buffers by the kernel in kilobytes.
kbcached
Amount of memory used to cache data by the kernel in kilobytes.
kbcommit
Amount of memory in kilobytes needed for current workload. This is an estimate of how much RAM/swap is needed to guarantee that there never
is out of memory.
%commit
Percentage of memory needed for current workload in relation to the total amount of memory (RAM+swap). This number may be greater than 100%
because the kernel usually overcommits memory.
kbactive
Amount of active memory in kilobytes (memory that has been used more recently and usually not reclaimed unless absolutely necessary).
kbinact
Amount of inactive memory in kilobytes (memory which has been less recently used. It is more eligible to be reclaimed for other purposes).
kbdirty
Amount of memory in kilobytes waiting to get written back to the disk.
#交换分区使用情况
-S Report swap space utilization statistics. The following values are displayed:
kbswpfree
Amount of free swap space in kilobytes.
kbswpused
Amount of used swap space in kilobytes.
%swpused
Percentage of used swap space.
kbswpcad
Amount of cached swap memory in kilobytes. This is memory that once was swapped out, is swapped back in but still also is in the swap area
(if memory is needed it doesn't need to be swapped out again because it is already in the swap area. This saves I/O).
%swpcad
Percentage of cached swap memory in relation to the amount of used swap space.
sar -r 一些内存参数说明
kbcommit,表示当前系统负载需要的内存,实际上是为了保证系统内存不溢出,对需要内存的估计值
kbactive,表示活跃内存,也就是最近使用过的内存,一般不会被系统回收
kbinact,表示非活跃内存,也就是不常访问的内存,有可能会被系统回收
执行dd
dd if=/dev/vda1 of=/dev/null bs=1G count=100
执行命令观察结果
sar -r -S 1
kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
3915640 3814304 123840 3.07 2200 25356 227316 1.83 17072 48604 96
kbswpfree kbswpused %swpused kbswpcad %swpcad
8388604 0 0.00 0 0.00
kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
3049236 3309968 990244 24.51 436124 25432 1278260 10.29 448640 482532 96
kbswpfree kbswpused %swpused kbswpcad %swpcad
8388604 0 0.00 0 0.00
kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
1310136 2690552 2729344 67.57 1553560 26472 1278260 10.29 1067048 1599744 228
kbswpfree kbswpused %swpused kbswpcad %swpcad
8388604 0 0.00 0 0.00
kbmemfree kbavail kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
112992 2687204 3926488 97.20 2745236 26748 1286232 10.35 1035120 2824604 8
kbswpfree kbswpused %swpused kbswpcad %swpcad
8388604 0 0.00 0 0.00
cachetop
PID UID CMD HITS MISSES DIRTIES READ_HIT% WRITE_HIT%
13767 root sh 417 0 0 100.0% 0.0%
13768 root grep 622 0 0 100.0% 0.0%
13764 root grep 641 0 0 100.0% 0.0%
13758 root dd 131840 131840 0 50.0% 50.0%
watch -d grep -A 15 'Normal' /proc/zoneinfo
Node 0, zone Normal
pages free 5155
min 4163
low 5203
high 6243
spanned 262144
present 262144
managed 245382
protection: (0, 0, 0, 0, 0)
nr_free_pages 5155
nr_zone_inactive_anon 59936
nr_zone_active_anon 1
nr_zone_inactive_file 87662
nr_zone_active_file 77480
nr_zone_unevictable 0
nr_zone_write_pending 0
通过sar命令观察,发现swap区一直没有被使用,swpused始终是0
内存的memused一直增长到97%,之后一直在97%左右徘徊
通过cachetop命令可以看到,dd执行后,读命中,写命中只有50%
再通过/proc/zoneinfo看内存区域页面使用情况
nr_free_pages 这个值在一个区间内不断变化,当小于min的时候就会回收内存页,回收后的值会大于high,之后又立刻分配了很多内存页,一直降低,等低到小于min后再次触发回收
nr_zone_active_anon,nr_zone_inactive_file 这两个值也在不断变化
在dd运行过程中,系统回收了匿名页和文件缓存,只有再分配再回收
通过上面情况可以发现,内存在不断回收不断分配,但因为设置了
swappiness 为0,所以一直没有使用swap区
使用swap最多的10个进程
for file in /proc/*/status; do awk '/VmSwap|Name|^Pid/ {printf $2 " "$3} END{print ""}' $file; done | sort -k 3 -n -r | head
writeback 27
watchdogd 38
watchdog/1 14
watchdog/0 11
ttm_swap 170
systemd-udevd 273 0 kB
systemd-resolve 371 0 kB
systemd-network 297 0 kB
systemd-logind 505 0 kB
systemd-journal 229 0 kB
当swappiness设置为60的时候
echo 60 > /proc/sys/vm/swappiness
cat /proc/sys/vm/swappiness
60
执行dd命令,再观察结果
dd if=/dev/vda1 of=/dev/null bs=1G count=200
sar -S -r 1
kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
89480 925428 91.18 19932 17212 1322700 42.50 422460 442352 0
kbswpfree kbswpused %swpused kbswpcad %swpcad
2041596 55552 2.65 10804 19.45
kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact kbdirty
72940 941968 92.81 21032 18852 1322700 42.50 431896 449072 8
kbswpfree kbswpused %swpused kbswpcad %swpcad
1943344 153804 7.33 7768 5.05
这次就看到了swpused在增长了
自己做实验的时候
Ubuntu的机器不管swiness设置的是0还是100,都不用swap
到CentOS的机器上,运行dd,才使用了swap
关闭再开启swap,也是一种常用的swap空间清理方式
swapoff -a && swapon -a
通常,降低Swap的使用,可以提高系统的整体性能,方式如下
1.禁止swap,当服务器内存足够大时,可以禁止swap,现在大部分云平台中的虚拟机都默认禁止swap
2.如果实在需要用到swap,可以尝试降低swappiness的值,减少内存回收时swap的使用倾向
3.响应延迟敏感的应用,如果他们可能在开启swap的服务器中运行,还可以使用库函数mlock()或者
mlockall()锁定内存,阻止他们的内存换出
/proc/sys/vm Document
man proc