Working on tracing.
[barrelfish] / usr / bench / mem_bench / memeasy.c
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 static volatile bool finished;
26
27 static void set_true(void* arg) {
28     *(bool*)arg = true;
29 }
30
31 static void sleep_until(delayus_t delay) {
32     struct deferred_event de;
33     deferred_event_init(&de);
34
35     bool can_continue = false;
36
37     struct event_closure ec;
38     ec.handler = set_true;
39     ec.arg = &can_continue;
40
41     errval_t err = deferred_event_register(&de, get_default_waitset(),
42                                            delay, ec);
43     if (err_is_fail(err)) {
44         USER_PANIC_ERR(err, "deferred event register failed.");
45     }
46
47     //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
48     while(!can_continue) {
49         messages_wait_and_handle_next();
50     }
51     //printf("%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);
52 }
53
54 static void after_prepare(void *arg)
55 {
56     debug_printf("after_prepare starts");
57     finished = true;
58 }
59
60 static errval_t init_tracing(void)
61 {
62     trace_reset_all();
63
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_XMPL,
69                                     TRACE_EVENT_XMPL_START, 0),
70                         TRACE_EVENT(TRACE_SUBSYS_XMPL,
71                                     TRACE_EVENT_XMPL_STOP, 0),
72                         0);
73 }
74
75 static void start_tracing(void)
76 {
77     // start the trace going by providing the start event
78     trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_START, 0);
79 }
80
81 static void stop_tracing(void)
82 {
83     // stop the trace by providing the stop event
84     trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_STOP, 0);
85 }
86
87 static void callback(void *arg)
88 {
89     debug_printf("callback invoked\n");
90
91     finished = true;
92 }
93
94 static 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
109 int 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         //printf("%s:%s:%d: i=%"PRIu64"\n",
176         //       __FILE__, __FUNCTION__, __LINE__, i);
177         start = bench_tsc();
178         //printf("%s:%s:%d: \n", __FILE__, __FUNCTION__, __LINE__);
179         err = cap_retype(frame, ram, ObjType_Frame, ram_bits);
180         if (err_is_fail(err)) {
181             USER_PANIC_ERR(err, "cap_retype failed.");
182         }
183         end = bench_tsc();
184
185         err = cap_delete(frame);
186         if (err_is_fail(err)) {
187             USER_PANIC_ERR(err, "cap_delete failed.");
188         }
189
190         if (sleep > 0) {
191             sleep_until(sleep);
192         }
193
194         runs[i] = end - start;
195     }
196
197     runs[0] = BENCH_IGNORE_WATERMARK;
198
199     printf("Average cycles %"PRIuCYCLES", Variance %"PRIuCYCLES"\n" \
200            "Average ms %"PRIu64" Variance ms %"PRIu64"\n",
201             bench_avg(runs, MAX_ITERATION),
202             bench_variance(runs, MAX_ITERATION),
203             bench_tsc_to_ms(bench_avg(runs, MAX_ITERATION)),
204             bench_tsc_to_ms(bench_variance(runs, MAX_ITERATION)));
205
206     finished = false;
207     stop_tracing();
208     // flush the trace buffer
209     dump_trace();
210
211     while(!finished) {
212         // Make sure this program is not exited before everything
213         // is completed.
214         event_dispatch_non_block(get_default_waitset());
215         thread_yield_dispatcher(NULL_CAP);
216     }
217
218
219     return 0;
220 }