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 #define LINESIZE 32 13 14 int thrashing_test(int test_runs, bool cache) { 15 int fds[4] = {-1, -1, -1, -1}; 16 char tmpnames[4][17] = { "thrashing1XXXXXX", "thrashing2XXXXXX", "thrashing3XXXXXX", "thrashing4XXXXXX" }; 17 volatile char *bufs[4] = {0}; 18 unsigned long long k; 19 int ret = -1; 20 struct timeval begin_time, end_time, elapsed_time, total_time; 21 unsigned long long filesize; 22 long num_pages; 23 long pagesize; 24 25 timerclear(&total_time); 26 27 num_pages = sysconf(_SC_PHYS_PAGES); 28 pagesize = sysconf(_SC_PAGE_SIZE); 29 if (num_pages < 0) { 30 fprintf(stderr, "failed to get the number of pages\n"); 31 return -1; 32 } 33 34 filesize = num_pages * pagesize / (ARRAY_SIZE(fds) - 1); 35 36 for (size_t i = 0; i < ARRAY_SIZE(fds); i++) { 37 fds[i] = create_tmp_file(tmpnames[i], filesize); 38 if (fds[i] < 0) { 39 goto err_fd; 40 } 41 } 42 43 for (size_t i = 0; i < ARRAY_SIZE(fds); i++) { 44 bufs[i] = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fds[i], 0); 45 if (bufs[i] == ((void *)-1)) { 46 fprintf(stderr, "Failed to mmap file: %s\n", strerror(errno)); 47 goto err; 48 } 49 if (!cache) { 50 //madvise and fadvise as random to prevent prefetching 51 ret = madvise((void *)bufs[i], filesize, MADV_RANDOM) || 52 posix_fadvise(fds[i], 0, filesize, POSIX_FADV_RANDOM); 53 if (ret) { 54 goto err; 55 } 56 } 57 } 58 59 for (int i = 0; i < test_runs; i++) { 60 for (size_t j = 0; j < ARRAY_SIZE(fds); j++) { 61 gettimeofday(&begin_time, NULL); 62 for (k = 0; k < filesize; k += pagesize) { 63 bufs[j][k]; 64 } 65 gettimeofday(&end_time, NULL); 66 67 timersub(&end_time, &begin_time, &elapsed_time); 68 timeradd(&total_time, &elapsed_time, &total_time); 69 } 70 } 71 72 printf("%scached thrashing: %llu MB/s\n", cache ? "" : "un", 73 (filesize * ARRAY_SIZE(fds) * test_runs * USEC_PER_SEC) / 74 (1024 * 1024 * (total_time.tv_sec * USEC_PER_SEC + total_time.tv_usec))); 75 76 ret = 0; 77 78 err: 79 for (size_t i = 0; i < ARRAY_SIZE(bufs) && bufs[i] != NULL; i++) { 80 munmap((void *)bufs[i], filesize); 81 } 82 err_fd: 83 for (size_t i = 0; i < ARRAY_SIZE(fds) && fds[i] >= 0; i++) { 84 close(fds[i]); 85 } 86 return ret; 87 } 88