Linux上のとあるファイルがページキャッシュに乗っているかどうかを調べたいなーと思ってGoogle先生にご相談したところ、こんなコマンドを教えてくれた。
ファイルをメモリにマップして、mincore(2)でページごとにRAMに存在するかどうかをチェックしているらしい。
mmapしても即メモリにロードされるわけではないのかぁ。
Cの部分だけ抜き出して、単体で動かしてみた。
#include <errno.h> /* errno */ #include <fcntl.h> /* fcntl, open */ #include <stdio.h> /* perror, fprintf, stderr, printf */ #include <stdlib.h> /* exit, calloc, free */ #include <string.h> /* strerror */ #include <sys/stat.h> /* stat, fstat */ #include <sys/types.h> /* size_t */ #include <unistd.h> /* sysconf, close */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> void fincore(char *filename) { int fd; struct stat st; void *pa = (char *)0; char *vec = (char *)0; register size_t n = 0; size_t pageSize = getpagesize(); register size_t pageIndex; int sum = 0; printf("pagesize: %ld\n", pageSize); fd = open(filename, 0); if (0 > fd) { perror("open"); return; } if (0 != fstat(fd, &st)) { perror("fstat"); close(fd); return; } printf("filesize: %ld\n", st.st_size); pa = mmap((void *)0, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); if (MAP_FAILED == pa) { perror("mmap"); close(fd); return; } printf("page num: %ld\n", (st.st_size+pageSize-1)/pageSize); /* vec = calloc(1, 1+st.st_size/pageSize); */ vec = calloc(1, (st.st_size+pageSize-1)/pageSize); if ((void *)0 == vec) { perror("calloc"); close(fd); return; } if (0 != mincore(pa, st.st_size, vec)) { /* perror("mincore"); */ fprintf(stderr, "mincore(%p, %lu, %p): %s\n", pa, (unsigned long)st.st_size, vec, strerror(errno)); free(vec); close(fd); return; } /* handle the results */ for (pageIndex = 0; pageIndex <= st.st_size/pageSize; pageIndex++) { if (vec[pageIndex]&1) { //printf("%lu\n", (unsigned long)pageIndex); sum++; } } free(vec); vec = (char *)0; munmap(pa, st.st_size); close(fd); printf("in memory pages: %d\n", sum); return; } int main(int argc, char **argv) { fincore(argv[1]); }
とりあえず適当なファイルをチェックしてみる。
[root@cthulhu work]# ./fincore_min /usr/lib/libvorbis.a
pagesize: 4096
filesize: 196894
page num: 49
in memory pages: 0
49ページあってキャッシュには全然乗っかってない。
/dev/nullに吐いてみる。
[root@cthulhu work]# cat /usr/lib/libvorbis.a > /dev/null
[root@cthulhu work]# ./fincore_min /usr/lib/libvorbis.a
pagesize: 4096
filesize: 196894
page num: 49
in memory pages: 49
キャッシュに乗りました、と。
でかいファイルで実行しても大丈夫かが、やや気になるなー。