• Ukieweb

    佳的博客

    曾梦想仗剑天涯,后来工作忙没去。

linux 内存中 page cached 等 缓存 的查看 使用和释放

1. 缓存的使用

Linux 对 cache 的使用没有规定上限,所以有时候我们的服务器上面,缓存比程序实际使用的内存还高,但是当程序申请的时候,缓存还是可以被内核自动回收的,所以对于程序而言,缓存被归纳到了可用内存中。

2. 内存中的几个概念

内存管理从三个层次管理内存,分别是node, zone ,page; 每个 zone 都有自己的 min low high,如下,但是单位是 page

[root@iZuf61cxey3d7znb5650r6Z /]# cat /proc/zoneinfo  |grep "Node 0, zone" -A4
Node 0, zone      DMA
  pages free     3977
        min      16
        low      20
        high     24
--
Node 0, zone    DMA32
  pages free     428606
        min      3011
        low      3763
        high     4516
--
Node 0, zone   Normal
  pages free     1809555
        min      13867
        low      17333
        high     20800

memory zone

对于多核 NUMA 系统而言,内存是分节点的,不同的 CPU 对不同的内存节点的访问速度是不一样的,所以 CPU 会优先去访问靠近自己的内存节点(即速度相对快的内存区域)。CPU 内部是依靠 MMU 来进行内存管理的,根据内存属性的不同,MMU 将一个内存节点内部又划分了不同的 zone。

64-bit 系统而言(即我们现在使用的系统),一个内存节点包含三个zone:Normal,DMA32,DMA, 64 位的 x86 物理机内存从高地址到低地址分为: Normal DMA32 DMA.随着地址降低

32-bit 系统而言,一个内存节点则是包括:Normal,Highmem,DMA。Highmem存在的目的是为了解决线性地址空间不够用的问题,在64-bit上由于有足够的线性地址空间所以就没了该zone。

page

内核把物理页作为内存管理的基本单位。linux 查看 OS 内存页 pagesize 的大小,返回值单位为 Bytes

[root@localhost nginx-1.8.0]# getconf PAGESIZE
4096
[root@localhost nginx-1.8.0]# getconf PAGE_SIZE
4096

3. 缓存的回收机制

Watermark 

每个内存 zone 都有一个数组 watermark,内核中定义了三个 watermark ( WMARK_MIN, WMARK_LOW, WMARK_HIGH,)来表示当前系统剩余的空闲内存程度。

  • high: 当剩余内存在high以上时,系统认为当前内存充足。

  • low:当剩余内存降低到low时,系统就认为内存已经不足了,会触发kswapd内核线程进行内存回收处理

  • min:当剩余内存在min时,则系统内存压力非常大。会触发 direct reclaim 进行内存回收处理

Kswapd

当空闲内存可用量 小于 low 的时候,会触发 kswapd 回收内存,当 kswapd 慢慢的将内存 回收到 high 水位,就开始继续睡眠

在 NUMA 系统中,每个 node 对应一个内核线程 kswapd,kswapd 在被唤醒后将扫描各个 zone 的内存使用状态,并据此进行必要的内存回收操作,因此 kswapd 的回收方式又被称为"background reclaim"

direct reclaim

min下的内存是保留给内核使用的;一般情况下min以下的内存是不会被分配给应用程序使用的,当到达min,会触发内存的 direct reclaim

在 direct reclaim 模式下,分配和回收是同步的关系,内存分配的过程会被内存回收的操作所阻塞增加等待的时间

4. 查看使用的缓存

查看总的使用情况,可使用 free 等命令

[root@iZuf61cxey3d7znb5650r6Z /]# free -m
              total        used        free      shared  buff/cache   available
Mem:          15885        3781        8759           4        3344       11617
Swap:             0           0           0

[root@iZuf61cxey3d7znb5650r6Z /]# cat /proc/meminfo 
MemTotal:       16266412 kB
MemFree:         8966696 kB
MemAvailable:   11893420 kB
Buffers:          123252 kB
Cached:          2729212 kB
SwapCached:            0 kB
Active:          5156864 kB
Inactive:        1150324 kB
Active(anon):    3455104 kB
Inactive(anon):     4336 kB
Active(file):    1701760 kB
Inactive(file):  1145988 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                48 kB
Writeback:             0 kB
AnonPages:       3454724 kB
Mapped:           273664 kB
Shmem:              4716 kB
Slab:             572464 kB
SReclaimable:     417228 kB
SUnreclaim:       155236 kB
KernelStack:       19792 kB
PageTables:        18772 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     8133204 kB
Committed_AS:    8716848 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       50784 kB
VmallocChunk:   34359593356 kB
HardwareCorrupted:     0 kB
AnonHugePages:   1867776 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      397184 kB
DirectMap2M:    13234176 kB
DirectMap1G:     5242880 kB
[root@iZuf61cxey3d7znb5650r6Z /]#

查看具体某个程序使用的缓存

目前没有找到哪个工具比较好,找了两个年代就远就没有试。但是可以按照下面的方法,以后自己写一个。

查看哪些进程使用的物理内存最多,就找到该进程打开的文件,然后用fincore查看这些文件的缓存使用率。

#!/bin/bash
#you have to install pcstat
if [ ! -f /data0/brokerproxy/pcstat ]
then
    echo "You haven't installed pcstat yet"
    echo "run \"go get github.com/tobert/pcstat\" to install"
    exit
fi
#find the top 10 processs' cache file
ps -e -o pid,rss|sort -nk2 -r|head -10 |awk '{print $1}'>/tmp/cache.pids
#find all the processs' cache file
#ps -e -o pid>/tmp/cache.pids
if [ -f /tmp/cache.files ]
then
    echo "the cache.files is exist, removing now "
    rm -f /tmp/cache.files
fi
while read line
do
    lsof -p $line 2>/dev/null|awk '{print $9}' >>/tmp/cache.files 
done</tmp/cache.pids
if [ -f /tmp/cache.pcstat ]
then
    echo "the cache.pcstat is exist, removing now"
    rm -f /tmp/cache.pcstat
fi
for i in `cat /tmp/cache.files`
do
    if [ -f $i ]
    then
        echo $i >>/tmp/cache.pcstat
    fi
done
/data0/brokerproxy/pcstat  `cat /tmp/cache.pcstat`
rm -f /tmp/cache.{pids,files,pcstat}

思想:

https://colobu.com/2017/03/07/what-is-in-linux-cached/

pcstat:

https://github.com/tobert/pcstat

fincore

# fincore --pages=false --summarize --only-cached * 

https://code.google.com/archive/p/linux-ftools/source/default/source

https://github.com/david415/linux-ftools

5. 缓存的回收

手动回收

/proc/sys/vm/drop_caches

To free pagecache:
    sync && echo 1 > /proc/sys/vm/drop_caches
    
To free reclaimable slab objects (includes dentries and inodes):
    sync && echo 2 > /proc/sys/vm/drop_caches
    
To free slab objects and pagecache:
    sync && echo 3 > /proc/sys/vm/drop_caches

1. 因为这个操作仅对 clean caches可回收的 slab进行回收,并不会对 dirty cache 进行回收,所以是非破坏性的。 这里的 sync 并不是避免丢失数据,而是为了最大化的释放内存。

2. 但是我们一定要尽量避免在业务高峰去操作,因为他会引发 CPU 和 I/O 操作,如果业务高峰,可能导致机器hung住

设置内核参数进行自动回收

具体参看文章: linux 内核优化 内存之缓存 写磁盘 /proc/sys/vm


0
0
下一篇:linux内核中 关于内存相关的参数 缓存 写磁盘 /proc/sys/vm

0 条评论

老佳啊

85后,大专学历,中原人士,家里没矿。

由于年轻时长的比较帅气,导致在别人眼里,我一直不谈恋爱的原因是清高,实则是自己的小自卑。最大的人生目标就是找一个相知相爱相容的人,共度余生。

和人相处时如果能感受到真诚,会非常注重彼此的关系,对别人没有什么心机,即使有利益冲突,一般也会以和为贵,因为在这个世界上,物质的东西,从来不会吸引到我。

特别迷恋那些大山大水,如果现在还能隐居,可能早就去了。对那些宏伟的有底蕴的人文景观比较不感冒。

从事于IT行业,却一直对厨房念念不忘,由于身材魁梧,总觉得自己上辈子是个将军,可惜这辈子没当兵,也不会打架。