1 #include <errno.h> 2 #include <fcntl.h> 3 #include <stdbool.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <sys/mman.h> 8 #include <sys/time.h> 9 10 #include "pagingtest.h" 11 12 int pageinout_test(int test_runs, bool cache, unsigned long long file_size) { 13 int fd; 14 char tmpname[] = "pageinoutXXXXXX"; 15 unsigned char *vec; 16 int i; 17 unsigned long long j; 18 volatile char *buf; 19 int ret = -1; 20 int rc; 21 struct timeval begin_time, end_time, elapsed_time, total_time_in, total_time_out; 22 long pagesize = sysconf(_SC_PAGE_SIZE); 23 24 timerclear(&total_time_in); 25 timerclear(&total_time_out); 26 27 fd = create_tmp_file(tmpname, file_size); 28 if (fd < 0) { 29 return -1; 30 } 31 32 vec = alloc_mincore_vec(file_size); 33 if (vec == NULL) { 34 goto err_alloc; 35 } 36 37 buf = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0); 38 if (buf == ((void *)-1)) { 39 fprintf(stderr, "Failed to mmap file: %s\n", strerror(errno)); 40 goto err_mmap; 41 } 42 43 if (!check_caching((void *)buf, vec, file_size, false)) { 44 goto err; 45 } 46 47 if (!cache) { 48 //madvise and fadvise as random to prevent prefetching 49 rc = madvise((void *)buf, file_size, MADV_RANDOM) || 50 posix_fadvise(fd, 0, file_size, POSIX_FADV_RANDOM); 51 if (rc) { 52 goto err; 53 } 54 } 55 56 for (i = 0; i < test_runs; i++) { 57 gettimeofday(&begin_time, NULL); 58 //read every page into the page cache 59 for (j = 0; j < file_size; j += pagesize) { 60 buf[j]; 61 } 62 gettimeofday(&end_time, NULL); 63 64 timersub(&end_time, &begin_time, &elapsed_time); 65 timeradd(&total_time_in, &elapsed_time, &total_time_in); 66 67 if (!check_caching((void *)buf, vec, file_size, true)) { 68 goto err; 69 } 70 71 gettimeofday(&begin_time, NULL); 72 rc = madvise((void *)buf, file_size, MADV_DONTNEED) || 73 posix_fadvise(fd, 0, file_size, POSIX_FADV_DONTNEED); 74 gettimeofday(&end_time, NULL); 75 if (rc) { 76 fprintf(stderr, "posix_fadvise/madvise DONTNEED failed\n"); 77 goto err; 78 } 79 80 timersub(&end_time, &begin_time, &elapsed_time); 81 timeradd(&total_time_out, &elapsed_time, &total_time_out); 82 83 if (!check_caching((void *)buf, vec, file_size, false)) { 84 goto err; 85 } 86 } 87 88 printf("%scached page-in: %llu MB/s\n", cache ? "" : "un", 89 (file_size * test_runs * USEC_PER_SEC) / 90 (1024 * 1024 * (total_time_in.tv_sec * USEC_PER_SEC + total_time_in.tv_usec))); 91 printf("%scached page-out (clean): %llu MB/s\n", cache ? "" : "un", 92 (file_size * test_runs * USEC_PER_SEC) / 93 (1024 * 1024 * (total_time_out.tv_sec * USEC_PER_SEC + total_time_out.tv_usec))); 94 95 ret = 0; 96 97 err: 98 munmap((void *)buf, file_size); 99 err_mmap: 100 free(vec); 101 err_alloc: 102 close(fd); 103 return ret; 104 } 105