Strip xseg stuff
[archipelago] / xseg / bench-xseg.h
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #include <xseg/protocol.h>
36 #include <bench-lfsr.h>
37
38 #ifdef __GNUC__
39 #define LIKELY(x)       __builtin_expect(!!(x),1)
40 #define UNLIKELY(x)     __builtin_expect(!!(x),0)
41 #else
42 #define LIKELY(x)       (x)
43 #define UNLIKELY(x)     (x)
44 #endif
45
46 /*
47  * If CLOCK_MONOTONIC_RAW is not defined in our system, use CLOCK_MONOTONIC
48  * instead. CLOCK_MONOTONIC_RAW is preferred since we are guaranteed that the
49  * clock won't skew.
50  */
51 #ifdef CLOCK_MONOTONIC_RAW
52 #define CLOCK_BENCH CLOCK_MONOTONIC_RAW
53 #else
54 #define CLOCK_BENCH CLOCK_MONOTONIC
55 #endif
56
57 #define MAX_ARG_LEN 10
58
59 /*
60  * Pattern type occupies 1st flag bit.
61  * If 0, it's sequential, if 1, it's random.
62  */
63 #define PATTERN_FLAG_POS 0
64 #define PATTERN_BITMASK 1
65 #define PATTERN_SEQ 0
66 #define PATTERN_RAND 1
67
68 /*
69  * Verify mode occupies 2nd and 3rd flag bit.
70  * If 01, it uses metadata for verification, if 11 it writes pseudorandom nums
71  * in chunk's memory range and if 00, it's off.
72  */
73 #define VERIFY_FLAG_POS 1
74 #define VERIFY_BITMASK 3        /* i.e. "11" in binary form */
75 #define VERIFY_NO 0
76 #define VERIFY_META 1
77 #define VERIFY_FULL 2
78
79 /* Timer insanity occupies 4th and 5th flag bit */
80 #define INSANITY_FLAG_POS 3
81 #define INSANITY_BITMASK 3      /* i.e. "11" in binary form */
82 #define INSANITY_SANE 0
83 #define INSANITY_ECCENTRIC 1
84 #define INSANITY_MANIC 2
85 #define INSANITY_PARANOID 3
86
87 /* Progress bar option occupies 6th flag bit */
88 #define PROGRESS_FLAG_POS 5
89 #define PROGRESS_BITMASK 3      /* i.e. "11" in binary form */
90 #define PROGRESS_NO 0
91 #define PROGRESS_YES 1
92
93 /* This is not part of flags per se, but is relative to progress */
94 #define PTYPE_REQ 0
95 #define PTYPE_IO 1
96 #define PTYPE_BOTH 2
97
98 /* Ping option occupies 7th flag bit */
99 #define PING_FLAG_POS 7
100 #define PING_BITMASK 1
101 #define PING_MODE_OFF 0
102 #define PING_MODE_ON 1
103
104 /*
105  * Current bench flags representation:
106  * 63
107  * .
108  * .
109  * .
110  * 8
111  * 7 <-- ping
112  * 6 <-- progress
113  * 5 <--   〃
114  * 4 <-- insanity
115  * 3 <--   〃
116  * 2 <-- verify
117  * 1 <--   〃
118  * 0 <-- pattern
119  */
120
121 /*
122  * Find position of flag, make it zero, get requested flag value, store it to
123  * this position
124  */
125 #define SET_FLAG(__ftype, __flag, __val)        \
126         __flag = (__flag & ~(__ftype##_BITMASK << __ftype##_FLAG_POS)) | \
127         (__val << __ftype##_FLAG_POS);
128
129 /* Apply bitmask to flags, shift result to the right to get correct value */
130 #define GET_FLAG(__ftype, __flag)                       \
131         (__flag & (__ftype##_BITMASK << __ftype##_FLAG_POS)) >> __ftype##_FLAG_POS
132
133 /*
134  * For now, the seed length is fixed to 9 digits whereas the object number
135  * length is fixed to fifteen digits.
136  */
137 #define SEEDLEN 9
138 #define OBJNUMLEN 15
139
140 struct bench {
141         uint64_t to; //Total number of objects (not for read/write)
142         uint64_t ts; //Total I/O size
143         uint64_t os; //Object size
144         uint64_t bs; //Block size
145         uint32_t iodepth; //Num of in-flight xseg reqs
146         xport dst_port;
147         xport src_port;
148         uint32_t op;    //xseg operation
149         uint64_t flags;
150         unsigned int interval;
151         struct peerd *peer;
152         struct req_status *status;
153         struct bench_lfsr *lfsr;
154         struct object_vars *objvars;
155         struct progress_report *rep;
156         struct timer *total_tm; //Total time for benchmark
157         struct timer *get_tm;   //Time for xseg_get_request
158         struct timer *sub_tm;   //Time for xseg_submit_request
159         struct timer *rec_tm;   //Time for xseg_receive_request
160 };
161
162 struct object_vars {
163         char name[XSEG_MAX_TARGETLEN];
164         int namelen;
165         char prefix[XSEG_MAX_TARGETLEN];
166         int prefixlen;
167         uint64_t seed;
168         int seedlen; /* seed length is hardcoded for now*/
169         uint64_t objnum;
170         int objnumlen;  /* object number length is hardcoded for now*/
171 };
172
173 struct req_status {
174         uint64_t max;           /* Max requests for benchmark */
175         uint64_t submitted;
176         uint64_t received;
177         uint64_t corrupted;     /* Requests that did not pass verification */
178         uint64_t failed;
179 };
180
181 struct progress_report {
182         int type;
183         uint64_t prev_recv;
184         uint64_t interval;
185         int lines;
186 };
187
188 /*
189  * Custom timespec. Made to calculate variance, where we need the square of a
190  * timespec struct. This struct should be more than enough to hold the square
191  * of the biggest timespec.
192  */
193 struct timespec2 {
194         unsigned long tv_sec2;
195         uint64_t tv_nsec2;
196 };
197
198 /*
199  * struct timer fields
200  * ====================
201  * completed: number of completed requests
202  * start_time: submission time of a request
203  * sum: the sum of elapsed times of every completed request
204  * sum_sq: the sum of the squares of elapsed times
205  * insanity: benchmarking level, higher means that the request associated with
206  *           this timer is more trivial.
207  */
208 struct timer {
209         struct timespec sum;
210         struct timespec2 sum_sq;
211         struct timespec start_time;
212         struct timespec elapsed_time;
213         uint64_t completed;
214         int insanity;
215 };
216
217 struct tm_result {
218         unsigned int s;
219         unsigned int ms;
220         unsigned int us;
221         unsigned int ns;
222 };
223
224 struct signature {
225         uint64_t id;
226         uint64_t object;
227         uint64_t offset;
228 };
229
230 struct bw {
231         double val;
232         char unit[5];
233 };
234
235 int bench_peerd_loop(void *arg);
236
237 void timer_start(struct bench *prefs, struct timer *sample_req);
238 void timer_stop(struct bench *prefs, struct timer *sample_tm,
239                 struct timespec *start);
240 int init_timer(struct timer **tm, int insanity);
241 uint64_t str2num(char *str);
242 int read_op(char *op);
243 int read_pattern(char *pattern);
244 int read_insanity(char *insanity);
245 int read_verify(char *insanity);
246 int read_progress(char *progress);
247 int read_progress_type(char *ptype);
248 uint64_t read_interval(struct bench *prefs, char *str_interval);
249 int read_ping(char *progress);
250 void clear_report_lines(int lines);
251 void print_total_res(struct bench *prefs);
252 void print_rec_res(struct bench *prefs);
253 void print_divider();
254 void print_req_stats(struct bench *prefs);
255 void print_io_stats(struct bench *prefs);
256 void print_progress(struct bench *prefs);
257 void print_dummy_progress(struct bench *prefs);
258 void print_remaining(struct bench *prefs);
259 void create_target(struct bench *prefs, struct xseg_request *req);
260 void create_chunk(struct bench *prefs, struct xseg_request *req, uint64_t new);
261 int read_chunk(struct bench *prefs, struct xseg_request *req);
262 uint64_t determine_next(struct bench *prefs);
263 uint64_t calculate_offset(struct bench *prefs, uint64_t new);
264 uint64_t calculate_interval(struct bench *prefs, uint64_t percentage);
265 int calculate_report_lines(struct bench *prefs);
266 int validate_seed(struct bench *prefs, unsigned long seed);
267
268 void inspect_obv(struct object_vars *obv);
269 uint64_t __get_object(struct bench *prefs, uint64_t new);
270