ファイルがキャッシュに乗ってのっているかどうかを調べる

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

キャッシュに乗りました、と。


でかいファイルで実行しても大丈夫かが、やや気になるなー。