3 * Currently only times various types of madvise frees.
13 #include <sys/sysctl.h>
15 #include "benchmark/helpers.h"
17 typedef enum test_variant
{
21 /* Arguments parsed from the command line */
22 typedef struct test_args
{
23 uint64_t ta_duration_seconds
;
25 test_variant_t ta_variant
;
29 static void print_help(char **argv
);
30 static void parse_arguments(int argc
, char** argv
, test_args_t
*args
);
31 static double madvise_free_test(const test_args_t
* args
);
33 * Allocate a buffer of the given size and fault in all of its pages.
35 static void *allocate_and_init_buffer(uint64_t size
);
37 * Fault in the pages in the given buffer.
39 static void fault_pages(unsigned char *buffer
, size_t size
, size_t stride
);
41 * Output the results of the test in pages / CPU second.
43 static void output_throughput(double throughput
);
46 static const char* kMadviseFreeArgument
= "MADV_FREE";
47 /* The VM page size */
48 static size_t kPageSize
= 0;
49 static const clockid_t kThreadCPUTimeClock
= CLOCK_THREAD_CPUTIME_ID
;
52 main(int argc
, char** argv
)
55 parse_arguments(argc
, argv
, &args
);
56 double throughput
= 0.0;
57 if (args
.ta_variant
== VARIANT_MADVISE_FREE
) {
58 throughput
= madvise_free_test(&args
);
60 fprintf(stderr
, "Unknown test variant\n");
63 output_throughput(throughput
);
68 madvise_free_test(const test_args_t
* args
)
71 assert(args
->ta_variant
== VARIANT_MADVISE_FREE
);
72 benchmark_log(args
->ta_verbose
, "Running madvise free test\n");
73 size_t time_elapsed_us
= 0;
75 double throughput
= 0;
77 while (time_elapsed_us
< args
->ta_duration_seconds
* kNumMicrosecondsInSecond
) {
78 benchmark_log(args
->ta_verbose
, "Starting iteration %zu\n", count
+ 1);
79 void* buffer
= allocate_and_init_buffer(args
->ta_size
);
80 benchmark_log(args
->ta_verbose
, "Allocated and faulted in test buffer\n");
81 struct timespec start_time
, end_time
;
82 ret
= clock_gettime(kThreadCPUTimeClock
, &start_time
);
84 madvise(buffer
, args
->ta_size
, MADV_FREE
);
86 ret_end
= clock_gettime(kThreadCPUTimeClock
, &end_time
);
89 time_elapsed_us
+= timespec_difference_us(&end_time
, &start_time
);
91 ret
= munmap(buffer
, args
->ta_size
);
93 benchmark_log(args
->ta_verbose
, "Completed iteration %zu\nMeasured %zu time on CPU so far.\n", count
+ 1, time_elapsed_us
);
97 assert(kPageSize
!= 0);
98 throughput
= (count
* args
->ta_size
) / ((double)time_elapsed_us
/ kNumMicrosecondsInSecond
);
103 allocate_and_init_buffer(uint64_t size
)
105 unsigned char *buffer
= NULL
;
108 if (kPageSize
== 0) {
109 size_t pagesize_size
= sizeof(kPageSize
);
110 ret
= sysctlbyname("vm.pagesize", &kPageSize
, &pagesize_size
, NULL
, 0);
112 assert(kPageSize
> 0);
115 buffer
= mmap_buffer(len
);
116 fault_pages(buffer
, len
, kPageSize
);
121 fault_pages(unsigned char *buffer
, size_t size
, size_t stride
)
123 volatile unsigned char val
;
124 for (unsigned char* ptr
= buffer
; ptr
< buffer
+ size
; ptr
+= stride
) {
130 parse_arguments(int argc
, char** argv
, test_args_t
*args
)
132 int current_positional_argument
= 0;
133 long duration
= -1, size_mb
= -1;
134 memset(args
, 0, sizeof(test_args_t
));
135 for (int current_argument
= 1; current_argument
< argc
; current_argument
++) {
136 if (argv
[current_argument
][0] == '-') {
137 if (strcmp(argv
[current_argument
], "-v") == 0) {
138 args
->ta_verbose
= true;
140 fprintf(stderr
, "Unknown argument %s\n", argv
[current_argument
]);
144 if (current_argument
>= argc
) {
149 if (current_positional_argument
== 0) {
150 if (strcasecmp(argv
[current_argument
], kMadviseFreeArgument
) == 0) {
151 args
->ta_variant
= VARIANT_MADVISE_FREE
;
156 current_positional_argument
++;
157 } else if (current_positional_argument
== 1) {
158 duration
= strtol(argv
[current_argument
], NULL
, 10);
163 current_positional_argument
++;
164 } else if (current_positional_argument
== 2) {
165 size_mb
= strtol(argv
[current_argument
], NULL
, 10);
170 current_positional_argument
++;
177 if (current_positional_argument
!= 3) {
178 fprintf(stderr
, "Expected 3 positional arguments. %d were supplied.\n", current_positional_argument
);
182 args
->ta_duration_seconds
= (uint64_t) duration
;
183 args
->ta_size
= ((uint64_t) size_mb
* (1UL << 20));
187 print_help(char** argv
)
189 fprintf(stderr
, "%s: <test-variant> [-v] duration_seconds size_mb\n", argv
[0]);
190 fprintf(stderr
, "\ntest variants:\n");
191 fprintf(stderr
, " %s Measure MADV_FREE time.\n", kMadviseFreeArgument
);
195 output_throughput(double throughput
)
197 printf("-----Results-----\n");
198 printf("Throughput (bytes / CPU second)\n");
199 printf("%f\n", throughput
);