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 
pageinout_test(int test_runs,unsigned long long file_size)11 int pageinout_test(int test_runs, unsigned long long file_size) {
12     int fd;
13     char tmpname[] = "pageinoutXXXXXX";
14     unsigned char *vec;
15     int i;
16     long long j;
17     volatile char *buf;
18     int ret = -1;
19     int rc;
20     struct timeval begin_time, end_time, elapsed_time, total_time_in, total_time_out;
21     long pagesize = sysconf(_SC_PAGE_SIZE);
22 
23     timerclear(&total_time_in);
24     timerclear(&total_time_out);
25 
26     fd = create_tmp_file(tmpname, file_size);
27     if (fd < 0) {
28         return -1;
29     }
30 
31     vec = alloc_mincore_vec(file_size);
32     if (vec == NULL) {
33         goto err_alloc;
34     }
35 
36     buf = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
37     if (buf == ((void *)-1)) {
38         fprintf(stderr, "Failed to mmap file: %s\n", strerror(errno));
39         goto err_mmap;
40     }
41 
42     if (!check_caching((void *)buf, vec, file_size, false)) {
43         goto err;
44     }
45 
46     for (i = 0; i < test_runs; i++) {
47         gettimeofday(&begin_time, NULL);
48         //Read backwards to prevent mmap prefetching
49         for (j = ((file_size - 1) & ~(pagesize - 1)); j >= 0; j -= pagesize) {
50             buf[j];
51         }
52         gettimeofday(&end_time, NULL);
53 
54         timersub(&end_time, &begin_time, &elapsed_time);
55         timeradd(&total_time_in, &elapsed_time, &total_time_in);
56 
57         if (!check_caching((void *)buf, vec, file_size, true)) {
58             goto err;
59         }
60 
61         gettimeofday(&begin_time, NULL);
62         rc = madvise((void *)buf, file_size, MADV_DONTNEED) ||
63                posix_fadvise(fd, 0, file_size, POSIX_FADV_DONTNEED);
64         gettimeofday(&end_time, NULL);
65         if (rc) {
66             fprintf(stderr, "posix_fadvise/madvise DONTNEED failed\n");
67             goto err;
68         }
69 
70         timersub(&end_time, &begin_time, &elapsed_time);
71         timeradd(&total_time_out, &elapsed_time, &total_time_out);
72 
73         if (!check_caching((void *)buf, vec, file_size, false)) {
74             goto err;
75         }
76     }
77 
78     printf("page-in: %llu MB/s\n", (file_size * test_runs * USEC_PER_SEC) /
79              (1024 * 1024 * (total_time_in.tv_sec * USEC_PER_SEC + total_time_in.tv_usec)));
80     printf("page-out (clean): %llu MB/s\n", (file_size * test_runs * USEC_PER_SEC) /
81              (1024 * 1024 * (total_time_out.tv_sec * USEC_PER_SEC + total_time_out.tv_usec)));
82 
83     ret = 0;
84 
85 err:
86     munmap((void *)buf, file_size);
87 err_mmap:
88     free(vec);
89 err_alloc:
90     close(fd);
91     return ret;
92 }
93