Quiero saber qué parte de un archivo enorme se almacena en caché en la memoria. Estoy usando un código de fincore para eso, que funciona de esta manera: el archivo está mmaped, luego fincore recorre el espacio de direcciones y páginas de verificación con mincore, pero es muy largo (varios minutos) debido al tamaño del archivo (varios TB)Linux: identificación de páginas en la memoria
¿Hay alguna forma de recorrer las páginas RAM usadas? Sería mucho más rápido, pero eso significa que debería obtener la lista de páginas usadas de algún lugar ... Sin embargo, no puedo encontrar una llamada al sistema conveniente que permita eso.
Aquí viene el código:
#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;
}
La asignación de un archivo de 8 TB requiere 2 mil millones de páginas de 4k. El tiempo de ejecución de 48 segundos de 'mincore' significa que se examinan 44.7 Mpages/seg. ¿Cuánto más rápido crees que esto podría pasar? Imprimir millones o miles de millones de líneas con 'printf()' tampoco es la cosa más rápida del mundo. –
No espero obtener mmap/mincore más rápido que eso; lo que me gustaría es reducir la longitud del bucle, posiblemente escaneando menos páginas ... – wazoox
'printf' suele ser un funcionamiento muy lento.Reemplácelo con algo como 'activePages ++' y vea cuánto tiempo lleva procesar el ciclo. Tenga en cuenta que 'vec' sigue siendo 2 GiB e incluso llamar' 'mincore' podría cambiar el contenido de la memoria caché a medida que se toca la memoria física dentro del espacio de direcciones virtuales asignado a' vec'. –