1 /* Copyright (c) 2005 Sean Chittenden <sean@chittenden.org>
2 *
3 * Permission is hereby granted, free of charge, to any person
4 * obtaining a copy of this software and associated documentation
5 * files (the "Software"), to deal in the Software without
6 * restriction, including without limitation the rights to use, copy,
7 * modify, merge, publish, distribute, sublicense, and/or sell copies
8 * of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23 #include <err.h>
24 #include <sysexits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "memcache.h"
31
32 double tt(const struct timeval *t1, const struct timeval *t2);
33
34 double
tt(const struct timeval * t1,const struct timeval * t2)35 tt(const struct timeval *t1, const struct timeval *t2) {
36 double ret;
37
38 ret = t2->tv_sec - t1->tv_sec;
39 ret += 0.000001 * (t2->tv_usec - t1->tv_usec);
40
41 return ret;
42 }
43
44
45 int
main(int argc,char * argv[])46 main(int argc, char *argv[]) {
47 struct memcache *mc = NULL;
48 u_int32_t num_tests = 0, valsize = 0;
49 u_int32_t i;
50 struct timeval t1, t2;
51 const char *key;
52 char *tests = NULL;
53 char *val;
54 u_int32_t keylen;
55 double addtime, deltime;
56 const char fmt[] = "%s\t%f\t%f\t%f\n";
57 struct memcache_req *req;
58 struct memcache_res *res;
59
60 if (argc > 1)
61 num_tests = strtol(argv[1], NULL, 10);
62
63 if (num_tests == 0)
64 num_tests = 10;
65
66 if (argc > 2)
67 valsize = strtol(argv[2], NULL, 10);
68
69 if (argc > 3)
70 tests = strdup(argv[3]);
71
72 if (tests == NULL)
73 tests = strdup("adgs");
74
75 if (valsize == 0)
76 valsize = 50;
77
78 val = (char *)malloc(valsize + 1);
79 memset(val, 69, valsize);
80 val[valsize] = '\0';
81
82 /* XXX I should add a min/max time value for each request */
83 printf("Value size:\t%d\n", valsize);
84 printf("Num tests:\t%d\n", num_tests);
85 printf("Test\tOps per second\tTotal Time\tTime per Request\n");
86
87 key = "bench_key";
88 keylen = strlen(key);
89
90 mc = mc_new();
91 if (mc == NULL)
92 err(EX_OSERR, "Unable to allocate a new memcache object");
93
94 mc_err_filter_del(MCM_ERR_LVL_INFO);
95 mc_err_filter_del(MCM_ERR_LVL_NOTICE);
96
97 mc_server_add4(mc, "localhost:11211");
98
99 /* Establish a connection */
100 mc_set(mc, key, keylen, val, valsize, 0, 0);
101
102 /* BEGIN set test, if specified */
103 if (strchr(tests, (int)'s') != NULL) {
104 if (gettimeofday(&t1, NULL) != 0)
105 err(EX_OSERR, "gettimeofday(2)");
106
107 for (i = 0; i < num_tests; i++) {
108 mc_set(mc, key, keylen, val, valsize, 0, 0);
109 }
110
111 if (gettimeofday(&t2, NULL) != 0)
112 err(EX_OSERR, "gettimeofday(2)");
113 /* END set test */
114 printf(fmt, "set", num_tests / tt(&t1, &t2), tt(&t1, &t2), tt(&t1, &t2) / num_tests);
115 }
116
117
118 if (strchr(tests, (int)'g') != NULL) {
119 /* BEGIN get request */
120 req = mc_req_new();
121 res = mc_req_add(req, key, keylen);
122 res->size = valsize;
123 res->val = malloc(res->size);
124 mc_res_free_on_delete(res, 1);
125
126 if (gettimeofday(&t1, NULL) != 0)
127 err(EX_OSERR, "gettimeofday(2)");
128
129 for (i = 0; i < num_tests; i++) {
130 mc_get(mc, req);
131 }
132
133 if (gettimeofday(&t2, NULL) != 0)
134 err(EX_OSERR, "gettimeofday(2)");
135
136 mc_req_free(req);
137 /* END get test */
138 printf(fmt, "get", num_tests / tt(&t1, &t2), tt(&t1, &t2), tt(&t1, &t2) / num_tests);
139 }
140
141
142
143 if (strchr(tests, 'a') != NULL || strchr(tests, 'd') != NULL) {
144 /* Run the add/delete test */
145 mc_delete(mc, key, keylen, 0);
146 addtime = deltime = 0.0;
147 for (i = 0; i < num_tests; i++) {
148 /* BEGIN add test */
149 if (strchr(tests, 'a') != NULL) {
150 if (gettimeofday(&t1, NULL) != 0)
151 err(EX_OSERR, "gettimeofday(2)");
152
153 mc_add(mc, key, keylen, val, valsize, 0, 0);
154
155 if (gettimeofday(&t2, NULL) != 0)
156 err(EX_OSERR, "gettimeofday(2)");
157
158 addtime += tt(&t1, &t2);
159 /* END add test */
160 }
161
162 /* BEGIN delete test */
163 if (strchr(tests, 'd') != NULL) {
164 if (gettimeofday(&t1, NULL) != 0)
165 err(EX_OSERR, "gettimeofday(2)");
166
167 mc_delete(mc, key, keylen, 0);
168
169 if (gettimeofday(&t2, NULL) != 0)
170 err(EX_OSERR, "gettimeofday(2)");
171
172 deltime += tt(&t1, &t2);
173 /* END delete test */
174 }
175 }
176
177 if (strchr(tests, 'a') != NULL)
178 printf(fmt, "add", num_tests / addtime, addtime, addtime / num_tests);
179
180 if (strchr(tests, 'd') != NULL)
181 printf(fmt, "delete", num_tests / deltime, deltime, deltime / num_tests);
182 }
183
184
185 free(tests);
186 free(val);
187 mc_free(mc);
188
189 return EX_OK;
190 }
191