我想知道在內存中緩存大文件的哪一部分。我使用的是fincore的一些代碼,它的工作方式如下:文件是mmaped,然後fincore遍歷地址空間並用mincore檢查頁面,但由於文件大小很長(幾分鐘) )。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;
}
映射一個8 TB文件需要20億4k頁面。 「mincore」的48秒運行時間表示正在檢查44.7 Mpages/sec。你認爲這可以走多快?用printf()打印數百或數十億行也不是世界上最快的事情。 – 2012-07-06 15:07:44
我不希望讓mmap/mincore比這更快;我想要的是減少循環的長度,可能通過掃描較少的頁面... – wazoox 2012-07-06 15:42:29
'printf'通常是非常慢的操作。將它替換爲'activePages ++'之類的東西,看看處理循環需要多少時間。注意'vec'仍然是2 GiB,甚至調用'mincore'可能會改變緩存的內容,因爲在分配給'vec'的虛擬地址空間內正在觸摸物理內存。 – 2012-07-06 15:50:29