#include #include #include #include #include #include #include #define BLOCK_SIZE 8192 #define INIT_SEED 1999 #define MAX_THREADS 8 size_t file_size; char* file_name; size_t n_prefetchers = 1; int use_fadvise; int n_iterations = 10*1024*1024; static off_t random_offset(uint64_t* seed) { off_t rnd = (3141592621u * *seed + 2718281829u) % 1000000007u; *seed = rnd; return rnd % file_size * BLOCK_SIZE; } void reader(void) { uint64_t seed = INIT_SEED; char page[BLOCK_SIZE]; time_t start = time(NULL); int i; int fd = open(file_name, O_RDONLY); assert(fd >= 0); for (i = 0; i < n_iterations; i++) { off_t offs = random_offset(&seed); ssize_t rc = pread(fd, page, sizeof page, offs); time_t now; assert(rc == BLOCK_SIZE); now = time(NULL); if (i % 1024 == 0 && now != start) { printf("%d: %.2f Mb/sec \r", i/1024, (double)(i+1)*BLOCK_SIZE/1024/1024/(now - start)); fflush(stdout); } } } void* prefetcher(void* arg) { size_t id = (size_t)arg; uint64_t seed = INIT_SEED; char page[BLOCK_SIZE]; int fd = open(file_name, O_RDONLY); int i; assert(fd >= 0); for (i = 0;;i++) { off_t offs = random_offset(&seed); if (i % n_prefetchers == id) { if (use_fadvise) { int rc = posix_fadvise(fd, offs, BLOCK_SIZE, POSIX_FADV_WILLNEED); assert(rc == 0); } else { ssize_t rc = pread(fd, page, sizeof page, offs); assert(rc == BLOCK_SIZE); } } } return 0; } int main(int argc, char* argv[]) { pthread_t prefetchers[MAX_THREADS]; int i; int fd; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'f': use_fadvise = 1; continue; case 'n': n_prefetchers = atoi(argv[++i]); continue; case 'i': n_iterations = atoi(argv[++i]); continue; default: help: fprintf(stderr, "prefetch [-f] [-n THREADS] [-i ITERATIONS] file\n"); return 1; } } else { file_name = argv[i]; } } if (file_name == NULL) { goto help; } fd = open(file_name, O_RDONLY); assert(fd >= 0); file_size = lseek(fd, 0, SEEK_END)/BLOCK_SIZE; assert(file_size != 0); for (i = 0; i < n_prefetchers; i++) { pthread_create(&prefetchers[i], NULL, prefetcher, (void*)(size_t)i); } reader(); puts("\nDone"); return 0; }