当发生内存泄漏,或运行大内存的应用,导致系统的内存资源紧张时。
1、导致OOM(Out Of Memory)
2、内存回收,也就是系统释放掉可以回收的内存,比如前面的缓存和缓冲区,就属于可回收内存。在内存管理中,通常被叫做 文件页(File-backed Page)。
大部分文件页,可以直接回收。而被应用程序修改过,并且暂时没写入磁盘的数据(脏页),得先写入磁盘,然后才能进行内存释放。写入磁盘方式
- 在应用程序中,通过系统调用 fsync,把脏页同步到磁盘中
- 系统,由内核线程 pdflush 负责这些脏页的刷新
应用程序动态分配的堆内存,也就是内存管理中的 匿名页(Anonymous Page),也不能直接释放。
1、原理
swap 就是把一块磁盘空间或者一个本地文件,当成内存来使用。包括
- 换出:把进程暂时不用的内存数据存储到磁盘中,并释放这些数据占用的内存
- 换入:在进程再次访问这些内存的时候,把他们从磁盘读到内存中来
2、衡量内存不足
1、直接内存回收
有新的大块内存分配需求,但剩余内存不足。系统需要回收一部分内存(如缓存),进而尽可能地满足新内存的请求。2、定期扫描回收
有一个专门的 内核线程 来定期回收内存,即kswapd0
它定义了三个内存阈值(watermark,水位)
这个 页低阈值,可以通过内核选项/proc/sys/vm/min_free_kbytes来设置。其他两个阈值,是根据这个计算的pages_low = pages_min*5/4pages_high = pages_min*3/2
3、NUMA与SWAP
在内存很多的情况下,也会发生 Swap,这是因为 在 NUMA 架构下,多个处理器被划分到不同 node 上,每个 node 有自己的本地存储空间。他们的内部存储空间,又分为不同的内存域(Zone)。
查看node情况
系统中只有一个 Node,也就是 Node 0 ,而且编号为 0 和 1 的两个 CPU, 都位于 Node 0 上。另外,Node 0 的内存大小为 3919 MB,剩余内存为 3017 MB。
三个内存阈值(页最小阈值、页低阈值和页高阈值),都可以通过内存域在 proc 文件系统中的接口 /proc/zoneinfo来查看。
可以看到剩余内存远高于 页最高阈值,kswapd0 也不会回收内存。
当某个 node 内存不足时,系统会从其他 node 寻找空闲内存,也可以从本地内存中回收内存。具体模式可以通过 /proc/sys/vm/zone_reclaim_mode 来调整。
- 默认的 0 ,表示既可以从其他 Node 寻找空闲内存,也可以从本地回收内存。
1、2、4 都表示只回收本地内存,2 表示可以回写脏数据回收内存,4 表示可以用 Swap 方式回收内存。
4、swappiness
对文件页回收,直接回收缓存,或把脏页写会磁盘后再回收
- 对匿名页回收,通过Swap机制,写入磁盘后释放内存
Linux 提供了一个 /proc/sys/vm/swappiness 选项,用来调整使用 Swap 的积极程度。
swappiness 的范围是 0-100,数值越大,越积极使用 Swap,也就是更倾向于回收匿名页;数值越小,越消极使用 Swap,也就是更倾向于回收文件页。
虽然 swappiness 的范围是 0-100,不过要注意,这并不是内存的百分比,而是调整 Swap 积极程度的权重,即使你把它设置成 0,当剩余内存 + 文件页小于页高阈值时,还是会发生 Swap。
5、工具
1、free
2、sar
查看系统内存和swap的实时使用情况
# 间隔1秒输出一组数据# -r表示显示内存使用情况,-S表示显示Swap使用情况sar -r -S 1
3、/proc/zoneinfo
# -d 表示高亮变化的字段# -A 表示仅显示Normal行以及之后的15行输出watch -d grep -A 15 'Normal' /proc/zoneinfo
4、smem
5、分析
当 /proc/zoneinfo 看到剩余内存(pages_free)在一个小范围内不停地波动。当它小于页低阈值(pages_low) 时,又会突然增大到一个大于页高阈值(pages_high)的值。
再结合刚刚用 sar 看到的 刚开始,剩余内存(kbmemfree)不断减少,而缓冲区(kbbuffers)则不断增大,由此可知,剩余内存不断分配给了缓冲区。一段时间后,剩余内存已经很小,而缓冲区占用了大部分内存。这时候,Swap 的使用开始逐渐增大,缓冲区和剩余内存则只在小范围内波动。
可以推导出,剩余内存和缓冲区的波动变化,正是由于内存回收和缓存再次分配的循环往复。
