巨大なファイルのどの部分がメモリにキャッシュされているか知りたい。私はfincoreからいくつかのコードを使用しています。これは、この方法で動作します。ファイルがmmapedされ、fincoreがアドレススペースをループし、mincoreでページをチェックしますが、ファイルサイズ(数TB) )。Linux:メモリ内のページを特定する
代わりに使用済みRAMページをループする方法はありますか?はるかに速くなりますが、それは私がどこかから使用されたページのリストを取得する必要があることを意味します...しかし、私はそれを可能にする便利なシステムコールを見つけることができません。
ここでコード来る:誰によってキャッシュされた
#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;
}
1つの8 TBファイルをマッピングするには、2億の4kページが必要です。 48秒間の「ミニコア」の実行時間は、調べられる44.7Mpages /秒を意味する。これがいかに速く進むと思うか? 'printf()'で数百億〜数十億行の行を印刷することも、世界で最速のものではありません。 –
私はmmap/mincoreがそれより速くなることを望んでいません。私が望むのは、ループの長さを減らすことです。おそらく少ないページをスキャンすることによって可能です。 – wazoox
'printf'は通常非常に遅い操作です。それを 'activePages ++'のようなものに置き換えて、ループを処理するのにかかる時間を確認してください。 'vec'がまだ2 GiBであり、' mincore'を呼び出すことさえ、 'vec'に割り当てられた仮想アドレス空間の中で物理メモリが触れられているので、キャッシュの内容を変更するかもしれません。 –