1 #include <errno.h> 2 #include <fcntl.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/mman.h> 7 #include <sys/time.h> 8 9 #include "pagingtest.h" 10 11 #define LINESIZE 32 12 13 int thrashing_test(int test_runs) { 14 int fds[4] = {-1, -1, -1, -1}; 15 char tmpnames[4][17] = { "thrashing1XXXXXX", "thrashing2XXXXXX", "thrashing3XXXXXX", "thrashing4XXXXXX" }; 16 volatile char *bufs[4] = {0}; 17 long long k; 18 int ret = -1; 19 struct timeval begin_time, end_time, elapsed_time, total_time; 20 unsigned long long filesize; 21 long num_pages; 22 long pagesize; 23 24 timerclear(&total_time); 25 26 num_pages = sysconf(_SC_PHYS_PAGES); 27 pagesize = sysconf(_SC_PAGE_SIZE); 28 if (num_pages < 0) { 29 fprintf(stderr, "failed to get the number of pages\n"); 30 return -1; 31 } 32 33 filesize = num_pages * pagesize / (ARRAY_SIZE(fds) - 1); 34 35 for (size_t i = 0; i < ARRAY_SIZE(fds); i++) { 36 fds[i] = create_tmp_file(tmpnames[i], filesize); 37 if (fds[i] < 0) { 38 goto err_fd; 39 } 40 } 41 42 for (size_t i = 0; i < ARRAY_SIZE(fds); i++) { 43 bufs[i] = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fds[i], 0); 44 if (bufs[i] == ((void *)-1)) { 45 fprintf(stderr, "Failed to mmap file: %s\n", strerror(errno)); 46 goto err; 47 } 48 } 49 50 for (int i = 0; i < test_runs; i++) { 51 for (size_t j = 0; j < ARRAY_SIZE(fds); j++) { 52 gettimeofday(&begin_time, NULL); 53 //Unfortunately when under memory pressure, fadvise and madvise stop working... 54 //Read backwards to prevent mmap prefetching 55 for (k = ((filesize - 1) & ~(pagesize - 1)); k >= 0; k -= pagesize) { 56 bufs[j][k]; 57 } 58 gettimeofday(&end_time, NULL); 59 60 timersub(&end_time, &begin_time, &elapsed_time); 61 timeradd(&total_time, &elapsed_time, &total_time); 62 } 63 } 64 65 printf("thrashing: %llu MB/s\n", (filesize * ARRAY_SIZE(fds) * test_runs * USEC_PER_SEC) / 66 (1024 * 1024 * (total_time.tv_sec * USEC_PER_SEC + total_time.tv_usec))); 67 68 ret = 0; 69 70 err: 71 for (size_t i = 0; i < ARRAY_SIZE(bufs) && bufs[i] != NULL; i++) { 72 munmap((void *)bufs[i], filesize); 73 } 74 err_fd: 75 for (size_t i = 0; i < ARRAY_SIZE(fds) && fds[i] >= 0; i++) { 76 close(fds[i]); 77 } 78 return ret; 79 } 80