Linux: identifying pages in memory

I want to know how much of the huge file is cached in memory. I use the code from fincore for this , which works as follows: the file has mmaped, then fincore loops in the address space and check the pages with mincore, but it is very long (several minutes) due to the file size (several TB).

Is there a way to loop through the used RAM pages? It would be much faster, but that means I have to get the list of used pages from somewhere ... However, I cannot find a convenient system call that would allow me to do this.

Here is the code:

#include <errno.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 
/* } */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/sysinfo.h>


void
fincore(char *filename) {
   int fd;
   struct stat st;

   struct sysinfo info;
   if (sysinfo(& info)) {
    perror("sysinfo");
    return;
   }

   void *pa = (char *)0;
   char *vec = (char *)0;
   size_t pageSize = getpagesize();
   register size_t pageIndex;

   fd = open(filename, 0);
   if (0 > fd) {
      perror("open");
      return;
   }

   if (0 != fstat(fd, &st)) {
      perror("fstat");
      close(fd);
      return;
   }

   pa = mmap((void *)0, st.st_size, PROT_NONE, MAP_SHARED, fd, 0);
   if (MAP_FAILED == pa) {
      perror("mmap");
      close(fd);
      return;
   }

   /* vec = calloc(1, 1+st.st_size/pageSize); */
   /* 2.2 sec for 8 TB */
   vec = calloc(1, (st.st_size+pageSize-1)/pageSize);
   if ((void *)0 == vec) {
      perror("calloc");
      close(fd);
      return;
   }

    /* 48 sec for 8 TB */
   if (0 != mincore(pa, st.st_size, vec)) {
      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 */
   /* 2m45s for 8 TB */
   for (pageIndex = 0; pageIndex <= st.st_size/pageSize; pageIndex++) {
      if (vec[pageIndex]&1) {
         printf("%zd\n", pageIndex);
      }
   }

   free(vec);
   vec = (char *)0;

   munmap(pa, st.st_size);
   close(fd);

   return;
}

int main(int argc, char *argv[]) {
    fincore(argv[1]);

    return 0;
}
+5
source share
2 answers

, , , , , - 64 1 . API, 2 , 16 . , , , , , , , .

( TLB Co), , ( ) , - OS .

, /proc/<PID>/smaps. , , ( Rss). mmap() ( , ), , , smaps , , . , , , , , .

+1

?

, . .

.

(, ) .

C .

, C .

, - - .

0

All Articles