Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / apps / rw-bench.c @ master

History | View | Annotate | Download (8.31 KB)

1
/* vim: set ai sw=4 sts=4 ts=4 : */
2

    
3
/***********************************************************************
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        Applications for the Global Data Plane
6
**        From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
7
**
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9
**        All rights reserved.
10
**
11
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16
**
17
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
**
22
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28
**  ----- END LICENSE BLOCK -----
29
***********************************************************************/
30

    
31
#include <gdp/gdp.h>
32
        // shouldn't be necessary, but we dig around inside gdp_datum_t
33
#include <gdp/gdp_priv.h>
34

    
35
#include <ep/ep_app.h>
36
#include <ep/ep_b64.h>
37
#include <ep/ep_dbg.h>
38
#include <ep/ep_string.h>
39
#include <event2/buffer.h>
40
#include <event2/util.h>
41

    
42
#include <sys/time.h>
43
#include <assert.h>
44
#include <stdio.h>
45
#include <unistd.h>
46
#include <getopt.h>
47

    
48
struct elapsed_time {
49
        long seconds;
50
        long millis;
51
};
52

    
53
void
54
avg_elapsed_time(struct elapsed_time *total_elapsed_time,
55
                size_t n, struct elapsed_time *out)
56
{
57
        assert(n > 0);
58
        out->millis = (total_elapsed_time->seconds * 1000) + total_elapsed_time->millis;
59
        out->millis /= n;
60
        out->seconds = out->millis / 1000;
61
        out->millis -= out->seconds * 1000;
62
}
63

    
64
void
65
sum_elapsed_time(struct elapsed_time elapsed_time[],
66
                size_t n, struct elapsed_time *out)
67
{
68
        size_t i;
69
        long new_seconds;
70
        out->seconds = 0;
71
        out->millis = 0;
72
        for (i = 0; i < n; ++i) {
73
                out->seconds += elapsed_time[i].seconds;
74
                out->millis += elapsed_time[i].millis;
75
        }
76
        new_seconds = out->millis / 1000;
77
        out->seconds += new_seconds;
78
        out->millis -= new_seconds * 1000;
79
}
80

    
81
void
82
get_elapsed_time(
83
                EP_TIME_SPEC *start_time, EP_TIME_SPEC *end_time,
84
                struct elapsed_time *out)
85
{
86
        out->millis = ((end_time->tv_sec - start_time->tv_sec) * 1000) +
87
                ((end_time->tv_nsec - start_time->tv_nsec) / (1000 * 1000));
88
        out->seconds = out->millis / 1000;
89
        out->millis -= out->seconds * 1000;
90
}
91

    
92
void
93
print_elapsed_time(FILE *stream, struct elapsed_time *elapsed_time)
94
{
95
        fprintf(stream, "Elapsed time = %lu.%03lu s\n",
96
                        elapsed_time->seconds, elapsed_time->millis);
97
}
98

    
99
int
100
random_in_range(unsigned int min, unsigned int max)
101
{
102
        int base_random = rand(); /* in [0, RAND_MAX] */
103
        if (RAND_MAX == base_random)
104
                return random_in_range(min, max);
105
        /* now guaranteed to be in [0, RAND_MAX) */
106
        int range = max - min, remainder = RAND_MAX % range, bucket = RAND_MAX
107
                / range;
108
        /* There are range buckets, plus one smaller interval
109
         within remainder of RAND_MAX */
110
        if (base_random < RAND_MAX - remainder)
111
        {
112
                return min + base_random / bucket;
113
        }
114
        else
115
        {
116
                return random_in_range(min, max);
117
        }
118
}
119

    
120
int
121
main(int argc, char *argv[])
122
{
123
        gdp_gin_t *gin_write;
124
        gdp_gin_t *gin_read;
125
        int opt;
126
        int num_records = 1000;
127
        int min_length = 1023;
128
        int max_length = 2047;
129
        int trials = 1;
130
        EP_STAT estat;
131
        char buf[200];
132

    
133
        while ((opt = getopt(argc, argv, "D:n:t:m:M:")) > 0)
134
        {
135
                switch (opt)
136
                {
137
                case 'D':
138
                        ep_dbg_set(optarg);
139
                        break;
140
                case 'n':
141
                        num_records = atoi(optarg);
142
                        break;
143
                case 't':
144
                        trials = atoi(optarg);
145
                        break;
146
                case 'm':
147
                        min_length = atoi(optarg);
148
                        break;
149
                case 'M':
150
                        max_length = atoi(optarg);
151
                        break;
152
                }
153
        }
154

    
155
        estat = gdp_init(NULL);
156
        if (!EP_STAT_ISOK(estat))
157
        {
158
                ep_app_error("GDP Initialization failed");
159
                goto fail0;
160
        }
161

    
162
        fprintf(stdout, "\nRunning trials\n\n");
163

    
164
        EP_TIME_SPEC start_time;
165
        EP_TIME_SPEC end_time;
166
        struct elapsed_time total_e_time;
167
        struct elapsed_time avg_e_time;
168
        struct elapsed_time *trial_write_times;
169
        struct elapsed_time *trial_read_times;
170
        char *data;
171
        size_t record_size;
172
        size_t max_record_size = max_length + 1;
173
        size_t data_size = num_records * (max_record_size);
174
        char *cur_record;
175
        char *cur_record_b64;
176
        gdp_name_t internal_name;
177
        gdp_pname_t printable_name;
178

    
179
        data = malloc(data_size);
180
        cur_record = malloc(max_record_size);
181
        cur_record_b64 = malloc((2 * max_length) + 1);
182
        trial_write_times = malloc(trials * sizeof(struct elapsed_time));
183
        trial_read_times = malloc(trials * sizeof(struct elapsed_time));
184

    
185
        int t;
186
        int i;
187

    
188
        for (t = 0; t < trials; ++t)
189
        {
190
                fprintf(stdout, "Trial %d\n", t);
191
                fprintf(stdout, "Generating %d records of length [%d, %d]\n",
192
                        num_records, min_length, max_length);
193
                for (i = 0; i < num_records; ++i)
194
                {
195
                        evutil_secure_rng_get_bytes(cur_record, max_length);
196
                        ep_b64_encode(cur_record, max_length, cur_record_b64,
197
                                (2 * max_length) + 1, EP_B64_ENC_URL);
198
                        record_size = random_in_range(min_length, max_length + 1);
199
                        memcpy(data + (i * max_record_size), cur_record_b64, record_size);
200
                        data[(i * max_record_size) + record_size] = '\0';
201
                        //fprintf(stdout, "Msgno = %d\n", i + 1);
202
                        //fprintf(stdout, "%s\n", &data[(i * max_record_size)]);
203
                        //fprintf(stdout, "record length: %lu\n", strlen(&data[(i * max_record_size)]));
204
                }
205

    
206
                estat = gdp_gob_create(NULL, NULL, &gin_write);
207

    
208
                EP_STAT_CHECK(estat, goto fail0);
209
                gdp_gin_print(gin_write, stdout);
210

    
211
                ep_time_now(&start_time);
212
                fprintf(stdout, "Writing data (start_time = %" PRIu64 ":%u)\n",
213
                                start_time.tv_sec, start_time.tv_nsec);
214
                for (i = 0; i < num_records; ++i)
215
                {
216
                        gdp_datum_t *datum = gdp_datum_new();
217
                        size_t dlen = strlen(&data[(i * max_record_size)]);
218

    
219
                        datum->recno = i + 1;
220
                        gdp_buf_reset(datum);
221
                        gdp_buf_write(datum->dbuf, &data[(i * max_record_size)], dlen);
222

    
223
                        estat = gdp_gin_append(gin_write, datum);
224
                        gdp_datum_free(datum);
225
                        EP_STAT_CHECK(estat, goto fail1);
226
                }
227
                ep_time_now(&end_time);
228
                fprintf(stdout, "Finished writing data (end_time = %" PRIu64 ":%u)\n",
229
                                end_time.tv_sec, end_time.tv_nsec);
230
                get_elapsed_time(&start_time, &end_time, &trial_write_times[t]);
231
                print_elapsed_time(stdout, &trial_write_times[t]);
232
                memcpy(internal_name, gdp_gin_getname(gin_write), sizeof internal_name);
233
                gdp_printable_name(internal_name, printable_name);
234
                gdp_gin_close(gin_write);
235
                estat = gdp_gob_open(internal_name, GDP_MODE_RO, NULL, &gin_read);
236
                ep_time_now(&start_time);
237
                fprintf(stdout, "Reading data (start_time = %" PRIu64 ":%u)\n",
238
                                start_time.tv_sec, start_time.tv_nsec);
239
                for (i = 0; i < num_records; ++i)
240
                {
241
                        gdp_datum_t *datum = gdp_datum_new();
242

    
243
                        estat = gdp_gin_read_by_recno(gin_read, i + 1, datum);
244
                        EP_STAT_CHECK(estat, goto fail2);
245
                        size_t dlen = gdp_buf_getlength(datum->dbuf);
246
                        gdp_buf_read(datum->dbuf, cur_record, dlen);
247
                        if (strncmp(data + (i * max_record_size), cur_record, dlen) != 0)
248
                        {
249
                                fprintf(stdout, "data mismatch:\n> expected: %s\n> got     : %s\n",
250
                                        data + (i * max_record_size), cur_record);
251
                        }
252

    
253
                        gdp_datum_free(datum);
254
//                        evbuffer_drain(evb, UINT_MAX);
255
                }
256
                ep_time_now(&end_time);
257
                fprintf(stdout, "Finished reading data (end_time = %" PRIu64 ":%u)\n",
258
                                end_time.tv_sec, end_time.tv_nsec);
259
                get_elapsed_time(&start_time, &end_time, &trial_read_times[t]);
260
                print_elapsed_time(stdout, &trial_read_times[t]);
261
                fprintf(stdout, "\n");
262
        }
263

    
264
        sum_elapsed_time(trial_read_times, trials, &total_e_time);
265
        avg_elapsed_time(&total_e_time, trials, &avg_e_time);
266

    
267
        fprintf(stdout, "Average read time per trial: %lu.%03lu s\n",
268
                        avg_e_time.seconds, avg_e_time.millis);
269

    
270
        sum_elapsed_time(trial_write_times, trials, &total_e_time);
271
        avg_elapsed_time(&total_e_time, trials, &avg_e_time);
272

    
273
        fprintf(stdout, "Average write time per trial: %lu.%03lu s\n", avg_e_time.seconds, avg_e_time.millis);
274

    
275
        free(trial_read_times);
276
        free(trial_write_times);
277
        free(cur_record_b64);
278
        free(cur_record);
279
        free(data);
280

    
281
        goto done;
282

    
283
fail2:
284
        gdp_gin_close(gin_read);
285

    
286
fail1:
287
        gdp_gin_close(gin_write);
288

    
289
fail0:
290
done:
291
        ep_app_message(estat, "exiting with status");
292
        return !EP_STAT_ISOK(estat);
293
}