/proc/$pid/status の RssFile の挙動を確かめる

/proc/$pid/status に含まれる RssFile という数値がどのように上下するのか分からなかったので、検証コードで挙動を確かめた

結論を先に書いておくと、プロセスが mmap(2) + MAP_FILE (ファイルの mmap ) しているサイズということらしくて、難しいもんでもなかった

Linux カーネルのドキュメントによる説明

https://www.kernel.org/doc/Documentation/filesystems/proc.txt には下記の通りの説明しかない

 RssFile                     size of resident file mappings

検証環境

Vagrant + CentOS7.3 3.10.0-514.26.2.el7.x86_64

検証内容

  • 検証用コードを実行して、 /proc/meminfo /proc/$pid/status pstop がどのような数値を返すかを観察する
  • 検証用コードを実行中に、sysctl vm.drop_caches=3 を実行して、上記の数値がどのように変化するかを観察する

検証用コード

1GB のテキストファイルを mmap(2) した後に、ポインタ操作でメジャーフォルトを起こしてデータをページキャッシュに載せるコードになる

CFLAGS="-g -O0 -std=gnu99 -W -Wall"
o=`basename $0`
o=".${o%.*}"
gcc ${CFLAGS} -o $o $0 && ./$o $*; exit
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

int main()
{
        int fd = open("/tmp/1000mb.txt", O_RDWR);
        if (fd == -1) {
                perror("open");
                exit(1);
        }

        size_t size = 1024 * 1024 * 1024;
        char *p = (char *)mmap(NULL, size, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
        if (p == MAP_FAILED) {
                perror("failed mmap");
                exit(2);
        }

        char c;
        for (size_t i = 0; i < size; i += 4096) {
                /* cause major fault */
                c = p[i];
                /* to remove -Wunused-but-set-variable */
                c = c;
        }

        /* Inactive(file) -> Active(file) */
        for (size_t i = 0; i < size; i += 4096) {
                c = p[i];
                c = c;
        }

        pause();
        exit(0);
}

検証手順

mmap(2) 用のファイルを作る

ファイルサイズはホストの搭載 RAM サイズに合わせて調整してください

perl -e 'print 1  x 1024  x 1024 x 1024' > /tmp/1000mb.txt
sync

ページキャッシュ, inode キャシュ, dentry キャッシュを破棄する

sudo sysctl vm.drop_caches=3

キャッシュを吹き飛ばしておいて数値の変化を把握しやくするのが目的

/proc/meminfo の値を記録する

[vagrant@localhost ~]$ cat /proc/meminfo
MemTotal:        3881976 kB
MemFree:         3705744 kB
MemAvailable:    3608720 kB
Buffers:               0 kB
Cached:            38408 kB
SwapCached:            0 kB
Active:            74440 kB
Inactive:          25112 kB
Active(anon):      61172 kB
Inactive(anon):     9136 kB
Active(file):      13268 kB
Inactive(file):    15976 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1572860 kB
SwapFree:        1572860 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:         61164 kB
Mapped:            25140 kB
Shmem:              9140 kB
Slab:              35552 kB
SReclaimable:      13184 kB
SUnreclaim:        22368 kB
KernelStack:        1888 kB
PageTables:         4672 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     3513848 kB
Committed_AS:     328436 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       11976 kB
VmallocChunk:   34359724032 kB
HardwareCorrupted:     0 kB
AnonHugePages:     10240 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       49088 kB
DirectMap2M:     4145152 kB

検証用コードを実行する

bash mmap.c

検証用コードを実行しているプロセスの /proc/$pid/status を記録する

  • RssFile: 1047928 kB となり、 mmap(2) したファイルサイズ (+α … libc 等のライブラリ ) 分がカウントされている
  • VmPeak , VmSize, VmHWM, VmRSS にもカウントされている
[vagrant@localhost ~]$ cat /proc/$(pgrep .mmap)/status
Name:   .mmap
State:  S (sleeping)
Tgid:   2544
Ngid:   0
Pid:    2544
PPid:   2537
TracerPid:      0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 1000 
VmPeak:  1052728 kB ⭐
VmSize:  1052728 kB ⭐
VmLck:         0 kB
VmPin:         0 kB
VmHWM:   1048732 kB ⭐
VmRSS:   1048732 kB ⭐
RssAnon:              84 kB
RssFile:         1048648 kB 🔥
RssShmem:              0 kB
VmData:       48 kB
VmStk:       132 kB
VmExe:         4 kB
VmLib:      1880 kB
VmPTE:      2076 kB
VmSwap:        0 kB
Threads:        1
SigQ:   0/15081
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000001fffffffff
CapAmb: 0000000000000000
Seccomp:        0
Cpus_allowed:   3
Cpus_allowed_list:      0-1
Mems_allowed:   00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list:      0
voluntary_ctxt_switches:        6324
nonvoluntary_ctxt_switches:     1

検証用コードを実行しているときの /proc/meminfo を記録する

  • 🔥 を付けた項目にカウントされている
[vagrant@localhost ~]$ cat /proc/meminfo
MemTotal:        3881976 kB
MemFree:         2631564 kB
MemAvailable:    3535780 kB
Buffers:               0 kB
Cached:          1108548 kB 🔥
SwapCached:            0 kB
Active:            75236 kB
Inactive:        1094604 kB 🔥
Active(anon):      61296 kB
Inactive(anon):     9136 kB
Active(file):      13940 kB
Inactive(file):  1085468 kB 🔥
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1572860 kB
SwapFree:        1572860 kB
Dirty:                12 kB
Writeback:             0 kB
AnonPages:         61440 kB
Mapped:          1073720 kB 🔥
Shmem:              9140 kB
Slab:              37416 kB
SReclaimable:      15032 kB
SUnreclaim:        22384 kB
KernelStack:        1920 kB
PageTables:         6800 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     3513848 kB
Committed_AS:     329076 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       11976 kB
VmallocChunk:   34359724032 kB
HardwareCorrupted:     0 kB
AnonHugePages:     10240 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       49088 kB
DirectMap2M:     4145152 kB

top の数値を記録する

  • RES と SHR どちらにもカウントされている
top - 08:41:25 up 22 min,  2 users,  load average: 0.06, 0.04, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  0.4 sy,  0.0 ni, 99.1 id,  0.3 wa,  0.0 hi,  0.1 si,  0.0 st
KiB Mem :  3881976 total,  2629904 free,   105144 used,  1146928 buff/cache
KiB Swap:  1572860 total,  1572860 free,        0 used.  3535032 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                  
 2544 vagrant   20   0 1052728 1.000g🔥1.000g🔥S   0.0 27.0   0:01.02 .mmap                                                                                                                                    

ps auxf の数値を記録する

RSS にもカウントされている

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
vagrant   2544  1.7 27.0 1052728 1048732 pts/0 S+   08:40   0:01  |               \_ ./.mmap

もう一度 ページキャッシュ, inode キャシュ, dentry キャッシュを破棄する

sudo sysctl vm.drop_caches=3

vm.drop_caches によるページキャッシュの破棄は mmap(2) しているページには作用しないようだ ( 正確なところはコードを読んで確かめたい)

[vagrant@localhost ~]$ cat /proc/meminfo
MemTotal:        3881976 kB
MemFree:         2652528 kB
MemAvailable:    3535704 kB
Buffers:               0 kB
Cached:          1087540 kB
SwapCached:            0 kB
Active:            74716 kB
Inactive:        1074168 kB
Active(anon):      61348 kB
Inactive(anon):     9136 kB
Active(file):      13368 kB
Inactive(file):  1065032 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1572860 kB
SwapFree:        1572860 kB
Dirty:                20 kB
Writeback:             0 kB
AnonPages:         61368 kB
Mapped:          1073720 kB
Shmem:              9140 kB
Slab:              37396 kB
SReclaimable:      14968 kB
SUnreclaim:        22428 kB
KernelStack:        1920 kB
PageTables:         6800 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     3513848 kB
Committed_AS:     329076 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       11976 kB
VmallocChunk:   34359724032 kB
HardwareCorrupted:     0 kB
AnonHugePages:     10240 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       49088 kB
DirectMap2M:     4145152 kB
[vagrant@localhost ~]$ 

検証用コードを実行しているプロセスを止めた後の /proc/meminfo を記録する

  • Mapped が減少した
  • Cached, Inactve(file) は減らない ( ページキャッシュとして残り続けている )

尚、Active(file)Inactive(file) かは今回の検証結果を左右するものでない ( http://mkosaki.blog46.fc2.com/blog-entry-884.html を読まれたし )

[vagrant@localhost ~]$ cat /proc/meminfo
MemTotal:        3881976 kB
MemFree:         2654592 kB
MemAvailable:    3537768 kB
Buffers:               0 kB
Cached:          1087540 kB
SwapCached:            0 kB
Active:            74412 kB
Inactive:        1074140 kB
Active(anon):      61016 kB
Inactive(anon):     9136 kB
Active(file):      13396 kB
Inactive(file):  1065004 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1572860 kB
SwapFree:        1572860 kB
Dirty:                20 kB
Writeback:             0 kB
AnonPages:         61084 kB
Mapped:            25140 kB 🔥
Shmem:              9140 kB
Slab:              37348 kB
SReclaimable:      14968 kB
SUnreclaim:        22380 kB
KernelStack:        1888 kB
PageTables:         4672 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     3513848 kB
Committed_AS:     328436 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       11976 kB
VmallocChunk:   34359724032 kB
HardwareCorrupted:     0 kB
AnonHugePages:     10240 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       49088 kB
DirectMap2M:     4145152 kB