2 * Copyright 2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
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.
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.
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.
39 #include <sys/syscall.h>
40 #include <sys/types.h>
42 #include <xseg/xseg.h>
47 #include <bench-xseg.h>
51 struct timespec delay = {0, 4000000};
54 * Convert string to size in bytes.
55 * If syntax is invalid, return 0. Values such as zero and non-integer
56 * multiples of segment's page size should not be accepted.
58 uint64_t str2num(char *str)
63 num = strtoll(str, &unit, 10);
64 if (strlen(unit) > 1) //Invalid syntax
66 else if (strlen(unit) < 1) //Plain number in bytes
87 * Converts struct timespec to double (units in nanoseconds)
89 static double timespec2double(struct timespec num)
91 return (double) (num.tv_sec * pow(10, 9) + num.tv_nsec);
94 int read_insanity(char *insanity)
96 if (strcmp(insanity, "sane") == 0)
98 if (strcmp(insanity, "eccentric") == 0)
100 if (strcmp(insanity, "manic") == 0)
102 if (strcmp(insanity, "paranoid") == 0)
107 int read_op(char *op)
109 if (strcmp(op, "read") == 0)
111 if (strcmp(op, "write") == 0)
113 if (strcmp(op, "info") == 0)
115 if (strcmp(op, "delete") == 0)
120 int read_pattern(char *pattern)
122 if (strcmp(pattern, "seq") == 0)
124 if (strcmp(pattern, "rand") == 0)
130 * Seperates a double number in seconds, msec, usec, nsec
131 * Expects a number in nanoseconds (e.g. a number from timespec2double)
133 static struct tm_result separate_by_order(double num)
135 struct tm_result res;
137 //The format we expect is the following:
139 // |-s-|-ms-|-us-|-ns|
140 //num = 123 456 789 012 . 000000000000
141 res.s = num / pow(10,9);
142 num = fmod(num, pow(10,9));
143 res.ms = num / pow(10,6);
144 num = fmod(num, pow(10,6));
146 res.ns = fmod(num, 1000);
151 void print_stats(struct bench *prefs)
156 printf("Requests total: %10lu\n", prefs->max_requests);
157 printf("Requests submitted: %10lu\n", prefs->sub_tm->completed);
158 printf("Requests received: %10lu\n", prefs->rec_tm->completed);
161 remaining = prefs->max_requests - prefs->rec_tm->completed;
163 printf("Requests remaining: %10lu\n", remaining);
165 printf("All requests have been served.\n");
168 void print_res(struct bench *prefs, struct timer *tm, char *type)
170 struct tm_result res;
173 sum = timespec2double(tm->sum);
174 res = separate_by_order(sum);
177 printf(" %s\n", type);
178 printf(" ========================\n");
179 printf(" |-s-||-ms-|-us-|-ns-|\n");
180 printf("Total time: %3u. %03u %03u %03u\n",
181 res.s, res.ms, res.us, res.ns);
183 if (!prefs->rec_tm->completed)
186 res = separate_by_order(sum / prefs->rec_tm->completed);
188 printf("Mean Time: %3u. %03u %03u %03u\n",
189 res.s, res.ms, res.us, res.ns);
194 void create_target(struct bench *prefs, struct xseg_request *req,
197 struct xseg *xseg = prefs->peer->xseg;
200 req_target = xseg_get_target(xseg, req);
202 //For read/write, the target object does not correspond to `new`, which is
203 //actually the chunk number. We need to div this number with the number of
204 //chunks in an object.
205 //FIXME: Make it more elegant
206 if (prefs->op == X_READ || prefs->op == X_WRITE)
207 new = new / (prefs->os / prefs->bs);
208 snprintf(req_target, TARGETLEN, "%s-%016lu", global_id, new);
209 XSEGLOG2(&lc, D, "Target name of request is %s\n", req_target);
212 void create_chunk(struct bench *prefs, struct xseg_request *req, uint64_t new)
214 struct xseg *xseg = prefs->peer->xseg;
217 //TODO: Fill data depening on validation level
218 req_data = xseg_get_data(xseg, req);
222 uint64_t determine_next(struct bench *prefs)
224 if ((prefs->flags & (1 << PATTERN_FLAG)) == IO_SEQ)
225 return prefs->sub_tm->completed;
227 return lfsr_next(prefs->lfsr);
231 //FIXME: this looks like a hack, handle it more elegantly
232 void create_id(unsigned long seed)
234 struct timespec timer_seed;
239 clock_gettime(CLOCK_MONOTONIC_RAW, &timer_seed);
240 global_seed = timer_seed.tv_nsec;
242 //nanoseconds can't be more than 9 digits
243 snprintf(global_id, IDLEN, "bench-%09lu", global_seed);
244 XSEGLOG2(&lc, I, "Global ID is %s\n", global_id);