]> git.ozlabs.org Git - ccan/blob - ccan/tdb/tools/speed.c
tdb: don't define _XOPEN_SOURCE ourselves, let config.h do it.
[ccan] / ccan / tdb / tools / speed.c
1 /* Simple speed test for TDB */
2 #include <err.h>
3 #include <time.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <sys/time.h>
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdbool.h>
13 #include <ccan/tdb/tdb.h>
14
15 /* Nanoseconds per operation */
16 static size_t normalize(const struct timeval *start,
17                         const struct timeval *stop,
18                         unsigned int num)
19 {
20         struct timeval diff;
21
22         timersub(stop, start, &diff);
23
24         /* Floating point is more accurate here. */
25         return (double)(diff.tv_sec * 1000000 + diff.tv_usec)
26                 / num * 1000;
27 }
28
29 static size_t file_size(void)
30 {
31         struct stat st;
32
33         if (stat("/tmp/speed.tdb", &st) != 0)
34                 return -1;
35         return st.st_size;
36 }
37
38 static int count_record(struct tdb_context *tdb,
39                         TDB_DATA key, TDB_DATA data, void *p)
40 {
41         int *total = p;
42         *total += *(int *)data.dptr;
43         return 0;
44 }
45
46 int main(int argc, char *argv[])
47 {
48         unsigned int i, j, num = 1000, stage = 0, stopat = -1;
49         int flags = TDB_DEFAULT;
50         TDB_DATA key, data;
51         struct tdb_context *tdb;
52         struct timeval start, stop;
53         bool transaction = false;
54
55         if (argv[1] && strcmp(argv[1], "--internal") == 0) {
56                 flags = TDB_INTERNAL;
57                 argc--;
58                 argv++;
59         }
60
61         if (argv[1] && strcmp(argv[1], "--transaction") == 0) {
62                 transaction = true;
63                 argc--;
64                 argv++;
65         }
66
67         tdb = tdb_open("/tmp/speed.tdb", 100003, flags, O_RDWR|O_CREAT|O_TRUNC,
68                        0600);
69         if (!tdb)
70                 err(1, "Opening /tmp/speed.tdb");
71
72         key.dptr = (void *)&i;
73         key.dsize = sizeof(i);
74         data = key;
75
76         if (argv[1]) {
77                 num = atoi(argv[1]);
78                 argv++;
79                 argc--;
80         }
81
82         if (argv[1]) {
83                 stopat = atoi(argv[1]);
84                 argv++;
85                 argc--;
86         }
87
88         if (transaction && tdb_transaction_start(tdb))
89                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
90
91         /* Add 1000 records. */
92         printf("Adding %u records: ", num); fflush(stdout);
93         gettimeofday(&start, NULL);
94         for (i = 0; i < num; i++)
95                 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
96                         errx(1, "Inserting key %u in tdb: %s",
97                              i, tdb_errorstr(tdb));
98         gettimeofday(&stop, NULL);
99         if (transaction && tdb_transaction_commit(tdb))
100                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
101         printf(" %zu ns (%zu bytes)\n",
102                normalize(&start, &stop, num), file_size());
103         if (++stage == stopat)
104                 exit(0);
105
106         if (transaction && tdb_transaction_start(tdb))
107                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
108
109         /* Finding 1000 records. */
110         printf("Finding %u records: ", num); fflush(stdout);
111         gettimeofday(&start, NULL);
112         for (i = 0; i < num; i++) {
113                 int *dptr;
114                 dptr = (int *)tdb_fetch(tdb, key).dptr;
115                 if (!dptr || *dptr != i)
116                         errx(1, "Fetching key %u in tdb gave %u",
117                              i, dptr ? *dptr : -1);
118         }
119         gettimeofday(&stop, NULL);
120         if (transaction && tdb_transaction_commit(tdb))
121                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
122         printf(" %zu ns (%zu bytes)\n",
123                normalize(&start, &stop, num), file_size());
124         if (++stage == stopat)
125                 exit(0);
126
127         if (transaction && tdb_transaction_start(tdb))
128                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
129
130         /* Missing 1000 records. */
131         printf("Missing %u records: ", num); fflush(stdout);
132         gettimeofday(&start, NULL);
133         for (i = num; i < num*2; i++) {
134                 int *dptr;
135                 dptr = (int *)tdb_fetch(tdb, key).dptr;
136                 if (dptr)
137                         errx(1, "Fetching key %u in tdb gave %u", i, *dptr);
138         }
139         gettimeofday(&stop, NULL);
140         if (transaction && tdb_transaction_commit(tdb))
141                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
142         printf(" %zu ns (%zu bytes)\n",
143                normalize(&start, &stop, num), file_size());
144         if (++stage == stopat)
145                 exit(0);
146
147         if (transaction && tdb_transaction_start(tdb))
148                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
149
150         /* Traverse 1000 records. */
151         printf("Traversing %u records: ", num); fflush(stdout);
152         i = 0;
153         gettimeofday(&start, NULL);
154         if (tdb_traverse(tdb, count_record, &i) != num)
155                 errx(1, "Traverse returned wrong number of records");
156         if (i != (num - 1) * (num / 2))
157                 errx(1, "Traverse tallied to %u", i);
158         gettimeofday(&stop, NULL);
159         if (transaction && tdb_transaction_commit(tdb))
160                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
161         printf(" %zu ns (%zu bytes)\n",
162                normalize(&start, &stop, num), file_size());
163         if (++stage == stopat)
164                 exit(0);
165
166         if (transaction && tdb_transaction_start(tdb))
167                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
168
169         /* Delete 1000 records (not in order). */
170         printf("Deleting %u records: ", num); fflush(stdout);
171         gettimeofday(&start, NULL);
172         for (j = 0; j < num; j++) {
173                 i = (j + 100003) % num;
174                 if (tdb_delete(tdb, key) != 0)
175                         errx(1, "Deleting key %u in tdb: %s",
176                              i, tdb_errorstr(tdb));
177         }
178         gettimeofday(&stop, NULL);
179         if (transaction && tdb_transaction_commit(tdb))
180                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
181         printf(" %zu ns (%zu bytes)\n",
182                normalize(&start, &stop, num), file_size());
183         if (++stage == stopat)
184                 exit(0);
185
186         if (transaction && tdb_transaction_start(tdb))
187                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
188
189         /* Re-add 1000 records (not in order). */
190         printf("Re-adding %u records: ", num); fflush(stdout);
191         gettimeofday(&start, NULL);
192         for (j = 0; j < num; j++) {
193                 i = (j + 100003) % num;
194                 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
195                         errx(1, "Inserting key %u in tdb: %s",
196                              i, tdb_errorstr(tdb));
197         }
198         gettimeofday(&stop, NULL);
199         if (transaction && tdb_transaction_commit(tdb))
200                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
201         printf(" %zu ns (%zu bytes)\n",
202                normalize(&start, &stop, num), file_size());
203         if (++stage == stopat)
204                 exit(0);
205
206         if (transaction && tdb_transaction_start(tdb))
207                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
208
209         /* Append 1000 records. */
210         printf("Appending %u records: ", num); fflush(stdout);
211         gettimeofday(&start, NULL);
212         for (i = 0; i < num; i++)
213                 if (tdb_append(tdb, key, data) != 0)
214                         errx(1, "Appending key %u in tdb: %s",
215                              i, tdb_errorstr(tdb));
216         gettimeofday(&stop, NULL);
217         if (transaction && tdb_transaction_commit(tdb))
218                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
219         printf(" %zu ns (%zu bytes)\n",
220                normalize(&start, &stop, num), file_size());
221         if (++stage == stopat)
222                 exit(0);
223
224         if (transaction && tdb_transaction_start(tdb))
225                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
226
227         /* Churn 1000 records: not in order! */
228         printf("Churning %u records: ", num); fflush(stdout);
229         gettimeofday(&start, NULL);
230         for (j = 0; j < num; j++) {
231                 i = (j + 1000019) % num;
232                 if (tdb_delete(tdb, key) != 0)
233                         errx(1, "Deleting key %u in tdb: %s",
234                              i, tdb_errorstr(tdb));
235                 i += num;
236                 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
237                         errx(1, "Inserting key %u in tdb: %s",
238                              i, tdb_errorstr(tdb));
239         }
240         gettimeofday(&stop, NULL);
241         if (transaction && tdb_transaction_commit(tdb))
242                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
243         printf(" %zu ns (%zu bytes)\n",
244                normalize(&start, &stop, num), file_size());
245
246         return 0;
247 }