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