1/** 2 * \file 3 * \brief Simple Memory Benchmark to test kernel infrastructure 4 */ 5/* 6 * Copyright (c) 2013, ETH Zurich. 7 * All rights reserved. 8 * 9 * This file is distributed under the terms in the attached LICENSE file. 10 * If you do not find this file, copies can be found by writing to: 11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 12 */ 13 14#include <stdlib.h> 15#include <stdio.h> 16#include <string.h> 17#include <assert.h> 18 19#include <barrelfish/barrelfish.h> 20#include <barrelfish/deferred.h> 21#include <bench/bench.h> 22#include <trace/trace.h> 23 24#define MAX_ITERATION 1000 25 26static volatile bool finished; 27 28static void set_true(void* arg) { 29 *(bool*)arg = true; 30} 31 32static void sleep_until(delayus_t delay) { 33 struct deferred_event de; 34 deferred_event_init(&de); 35 36 bool can_continue = false; 37 38 struct event_closure ec; 39 ec.handler = set_true; 40 ec.arg = &can_continue; 41 42 errval_t err = deferred_event_register(&de, get_default_waitset(), 43 delay, ec); 44 if (err_is_fail(err)) { 45 USER_PANIC_ERR(err, "deferred event register failed."); 46 } 47 48 //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); 49 while(!can_continue) { 50 messages_wait_and_handle_next(); 51 } 52 //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__); 53} 54 55static void after_prepare(void *arg) 56{ 57 debug_printf("after_prepare starts"); 58 finished = true; 59} 60 61static errval_t init_tracing(void) 62{ 63 trace_reset_all(); 64 debug_printf("after trace reset\n"); 65 66 // Tell the trace system when to start and stop. We can also 67 // provide an overriding maximum duration (in cycles) as the last parameter. 68 return trace_control(TRACE_EVENT(TRACE_SUBSYS_BENCH, 69 TRACE_EVENT_BENCH_START, 0), 70 TRACE_EVENT(TRACE_SUBSYS_BENCH, 71 TRACE_EVENT_BENCH_STOP, 0), 72 0); 73} 74 75static void start_tracing(void) 76{ 77 // start the trace going by providing the start event 78 TRACE(BENCH, START, 0); 79} 80 81static void stop_tracing(void) 82{ 83 // stop the trace by providing the stop event 84 TRACE(BENCH, STOP, 0); 85} 86 87static void callback(void *arg) 88{ 89 debug_printf("callback invoked\n"); 90 91 finished = true; 92} 93 94static void dump_trace(void) 95{ 96 // dump the trace on the output. We can copy and paste it 97 // to use in Aquarium. 98 99 debug_printf("the trace dump\n"); 100 101 // Let the trace framework decide where to flush to 102 trace_flush(MKCLOSURE(callback, NULL)); 103 104 debug_printf("finished trace dump\n"); 105 106} 107 108 109int main(int argc, char** argv) 110{ 111 uint64_t sleep = 0; 112 uint64_t ram_bits = 20; 113 errval_t err; 114 115 printf("%s:%s:%d: argc = %d\n", __FILE__, __FUNCTION__, __LINE__, argc); 116 if (argc > 3) { 117 printf("%s:%s:%d: Usage: %s <ram bits> <sleep ms>\n", 118 __FILE__, __FUNCTION__, __LINE__, argv[0]); 119 } else if (argc == 3) { 120 sleep = atoll(argv[2]); 121 ram_bits = atoll(argv[1]); 122 } else if (argc == 2) { 123 ram_bits = atoll(argv[1]); 124 } 125 printf("%s:%s:%d: Use ram_bits = %"PRIu64"\n", 126 __FILE__, __FUNCTION__, __LINE__, ram_bits); 127 printf("%s:%s:%d: Use sleep = %"PRIu64"\n", 128 __FILE__, __FUNCTION__, __LINE__, sleep); 129 130 131 finished = false; 132 133 err = init_tracing(); 134 if (err_is_fail(err)) { 135 DEBUG_ERR(err, "initialising tracing"); 136 return EXIT_FAILURE; 137 } 138 139 // Make sure all subsystems get logged. 140 trace_set_all_subsys_enabled(true); 141 142 debug_printf("after init tracing\n"); 143 144 // Prepare the tracing framework. This is optional. 145 trace_prepare(MKCLOSURE(after_prepare, NULL)); 146 147 while(!finished) { 148 // Make sure this program is not exited before everything 149 // is completed. 150 event_dispatch_non_block(get_default_waitset()); 151 thread_yield_dispatcher(NULL_CAP); 152 } 153 154 155 bench_init(); 156 cycles_t runs[MAX_ITERATION]; 157 158 start_tracing(); 159 160 uint64_t start, end; 161 162 struct capref ram; 163 err = ram_alloc(&ram, ram_bits); 164 if (err_is_fail(err)) { 165 USER_PANIC_ERR(err, "ram_alloc failed."); 166 } 167 168 struct capref frame; 169 err = slot_alloc(&frame); 170 if (err_is_fail(err)) { 171 USER_PANIC_ERR(err, "slot_alloc failed."); 172 } 173 174 for (size_t i=0; i<MAX_ITERATION; i++) { 175 TRACE(BENCH, ROUND_START, 0); 176 //printf("%s:%s:%d: i=%"PRIu64"\n", 177 // __FILE__, __FUNCTION__, __LINE__, i); 178 start = bench_tsc(); 179 //printf("%s:%s:%d: \n", __FILE__, __FUNCTION__, __LINE__); 180 err = cap_retype(frame, ram, 0, ObjType_Frame, 1UL << ram_bits, 1); 181 if (err_is_fail(err)) { 182 USER_PANIC_ERR(err, "cap_retype failed."); 183 } 184 end = bench_tsc(); 185 186 err = cap_delete(frame); 187 if (err_is_fail(err)) { 188 USER_PANIC_ERR(err, "cap_delete failed."); 189 } 190 191 if (sleep > 0) { 192 sleep_until(sleep); 193 } 194 TRACE(BENCH, ROUND_END, 0); 195 196 runs[i] = end - start; 197 } 198 199 runs[0] = BENCH_IGNORE_WATERMARK; 200 201 printf("Average cycles %"PRIuCYCLES", Variance %"PRIuCYCLES"\n" \ 202 "Average ms %"PRIu64" Variance ms %"PRIu64"\n", 203 bench_avg(runs, MAX_ITERATION), 204 bench_variance(runs, MAX_ITERATION), 205 bench_tsc_to_ms(bench_avg(runs, MAX_ITERATION)), 206 bench_tsc_to_ms(bench_variance(runs, MAX_ITERATION))); 207 208 finished = false; 209 stop_tracing(); 210 // flush the trace buffer 211 dump_trace(); 212 213 while(!finished) { 214 // Make sure this program is not exited before everything 215 // is completed. 216 event_dispatch_non_block(get_default_waitset()); 217 thread_yield_dispatcher(NULL_CAP); 218 } 219 220 221 return 0; 222} 223