]> git.ozlabs.org Git - ccan/blob - ccan/tdb2/tools/speed.c
84dff9968f795a362ac3ee70eecef6db2706da6d
[ccan] / ccan / tdb2 / 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/tdb2/tdb2.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         bool transaction = false;
51         TDB_DATA key, data;
52         struct tdb_context *tdb;
53         struct timeval start, stop;
54         union tdb_attribute seed;
55
56         /* Try to keep benchmarks even. */
57         seed.base.attr = TDB_ATTRIBUTE_SEED;
58         seed.base.next = NULL;
59         seed.seed.seed = 0;
60
61         if (argv[1] && strcmp(argv[1], "--internal") == 0) {
62                 flags = TDB_INTERNAL;
63                 argc--;
64                 argv++;
65         }
66         if (argv[1] && strcmp(argv[1], "--transaction") == 0) {
67                 transaction = true;
68                 argc--;
69                 argv++;
70         }
71
72         tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR|O_CREAT|O_TRUNC,
73                        0600, &seed);
74         if (!tdb)
75                 err(1, "Opening /tmp/speed.tdb");
76
77         key.dptr = (void *)&i;
78         key.dsize = sizeof(i);
79         data = key;
80
81         if (argv[1]) {
82                 num = atoi(argv[1]);
83                 argv++;
84                 argc--;
85         }
86
87         if (argv[1]) {
88                 stopat = atoi(argv[1]);
89                 argv++;
90                 argc--;
91         }
92
93         if (transaction && tdb_transaction_start(tdb))
94                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
95
96         /* Add 1000 records. */
97         printf("Adding %u records: ", num); fflush(stdout);
98         gettimeofday(&start, NULL);
99         for (i = 0; i < num; i++)
100                 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
101                         errx(1, "Inserting key %u in tdb: %s",
102                              i, tdb_errorstr(tdb));
103         gettimeofday(&stop, NULL);
104         if (transaction && tdb_transaction_commit(tdb))
105                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
106         printf(" %zu ns (%zu bytes)\n",
107                normalize(&start, &stop, num), file_size());
108         if (++stage == stopat)
109                 exit(0);
110
111         if (transaction && tdb_transaction_start(tdb))
112                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
113
114         /* Finding 1000 records. */
115         printf("Finding %u records: ", num); fflush(stdout);
116         gettimeofday(&start, NULL);
117         for (i = 0; i < num; i++) {
118                 int *dptr;
119                 dptr = (int *)tdb_fetch(tdb, key).dptr;
120                 if (!dptr || *dptr != i)
121                         errx(1, "Fetching key %u in tdb gave %u",
122                              i, dptr ? *dptr : -1);
123         }
124         gettimeofday(&stop, NULL);
125         if (transaction && tdb_transaction_commit(tdb))
126                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
127         printf(" %zu ns (%zu bytes)\n",
128                normalize(&start, &stop, num), file_size());
129         if (++stage == stopat)
130                 exit(0);
131
132         if (transaction && tdb_transaction_start(tdb))
133                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
134
135         /* Missing 1000 records. */
136         printf("Missing %u records: ", num); fflush(stdout);
137         gettimeofday(&start, NULL);
138         for (i = num; i < num*2; i++) {
139                 int *dptr;
140                 dptr = (int *)tdb_fetch(tdb, key).dptr;
141                 if (dptr)
142                         errx(1, "Fetching key %u in tdb gave %u", i, *dptr);
143         }
144         gettimeofday(&stop, NULL);
145         if (transaction && tdb_transaction_commit(tdb))
146                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
147         printf(" %zu ns (%zu bytes)\n",
148                normalize(&start, &stop, num), file_size());
149         if (++stage == stopat)
150                 exit(0);
151
152         if (transaction && tdb_transaction_start(tdb))
153                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
154
155         /* Traverse 1000 records. */
156         printf("Traversing %u records: ", num); fflush(stdout);
157         i = 0;
158         gettimeofday(&start, NULL);
159         if (tdb_traverse(tdb, count_record, &i) != num)
160                 errx(1, "Traverse returned wrong number of records");
161         if (i != (num - 1) * (num / 2))
162                 errx(1, "Traverse tallied to %u", i);
163         gettimeofday(&stop, NULL);
164         if (transaction && tdb_transaction_commit(tdb))
165                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
166         printf(" %zu ns (%zu bytes)\n",
167                normalize(&start, &stop, num), file_size());
168         if (++stage == stopat)
169                 exit(0);
170
171         if (transaction && tdb_transaction_start(tdb))
172                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
173
174         /* Delete 1000 records (not in order). */
175         printf("Deleting %u records: ", num); fflush(stdout);
176         gettimeofday(&start, NULL);
177         for (j = 0; j < num; j++) {
178                 i = (j + 100003) % num;
179                 if (tdb_delete(tdb, key) != 0)
180                         errx(1, "Deleting key %u in tdb: %s",
181                              i, tdb_errorstr(tdb));
182         }
183         gettimeofday(&stop, NULL);
184         if (transaction && tdb_transaction_commit(tdb))
185                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
186         printf(" %zu ns (%zu bytes)\n",
187                normalize(&start, &stop, num), file_size());
188         if (++stage == stopat)
189                 exit(0);
190
191         if (transaction && tdb_transaction_start(tdb))
192                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
193
194         /* Re-add 1000 records (not in order). */
195         printf("Re-adding %u records: ", num); fflush(stdout);
196         gettimeofday(&start, NULL);
197         for (j = 0; j < num; j++) {
198                 i = (j + 100003) % num;
199                 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
200                         errx(1, "Inserting key %u in tdb: %s",
201                              i, tdb_errorstr(tdb));
202         }
203         gettimeofday(&stop, NULL);
204         if (transaction && tdb_transaction_commit(tdb))
205                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
206         printf(" %zu ns (%zu bytes)\n",
207                normalize(&start, &stop, num), file_size());
208         if (++stage == stopat)
209                 exit(0);
210
211         if (transaction && tdb_transaction_start(tdb))
212                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
213
214         /* Append 1000 records. */
215         printf("Appending %u records: ", num); fflush(stdout);
216         gettimeofday(&start, NULL);
217         for (i = 0; i < num; i++)
218                 if (tdb_append(tdb, key, data) != 0)
219                         errx(1, "Appending key %u in tdb: %s",
220                              i, tdb_errorstr(tdb));
221         gettimeofday(&stop, NULL);
222         if (transaction && tdb_transaction_commit(tdb))
223                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
224         printf(" %zu ns (%zu bytes)\n",
225                normalize(&start, &stop, num), file_size());
226         if (++stage == stopat)
227                 exit(0);
228
229         if (transaction && tdb_transaction_start(tdb))
230                 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
231
232         /* Churn 1000 records: not in order! */
233         printf("Churning %u records: ", num); fflush(stdout);
234         gettimeofday(&start, NULL);
235         for (j = 0; j < num; j++) {
236                 i = (j + 1000019) % num;
237                 if (tdb_delete(tdb, key) != 0)
238                         errx(1, "Deleting key %u in tdb: %s",
239                              i, tdb_errorstr(tdb));
240                 i += num;
241                 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
242                         errx(1, "Inserting key %u in tdb: %s",
243                              i, tdb_errorstr(tdb));
244         }
245         gettimeofday(&stop, NULL);
246         if (transaction && tdb_transaction_commit(tdb))
247                 errx(1, "committing transaction: %s", tdb_errorstr(tdb));
248         printf(" %zu ns (%zu bytes)\n",
249                normalize(&start, &stop, num), file_size());
250
251         return 0;
252 }