1 /* Simple speed test for TDB */
13 #include <ccan/tdb2/tdb2.h>
15 /* Nanoseconds per operation */
16 static size_t normalize(const struct timeval *start,
17 const struct timeval *stop,
22 timersub(stop, start, &diff);
24 /* Floating point is more accurate here. */
25 return (double)(diff.tv_sec * 1000000 + diff.tv_usec)
29 static size_t file_size(void)
33 if (stat("/tmp/speed.tdb", &st) != 0)
38 static int count_record(struct tdb_context *tdb,
39 TDB_DATA key, TDB_DATA data, void *p)
42 *total += *(int *)data.dptr;
46 int main(int argc, char *argv[])
48 unsigned int i, j, num = 1000, stage = 0, stopat = -1;
49 int flags = TDB_DEFAULT;
50 bool transaction = false;
52 struct tdb_context *tdb;
53 struct timeval start, stop;
54 union tdb_attribute seed;
56 /* Try to keep benchmarks even. */
57 seed.base.attr = TDB_ATTRIBUTE_SEED;
58 seed.base.next = NULL;
61 if (argv[1] && strcmp(argv[1], "--internal") == 0) {
66 if (argv[1] && strcmp(argv[1], "--transaction") == 0) {
72 tdb = tdb_open("/tmp/speed.tdb", flags, O_RDWR|O_CREAT|O_TRUNC,
75 err(1, "Opening /tmp/speed.tdb");
77 key.dptr = (void *)&i;
78 key.dsize = sizeof(i);
88 stopat = atoi(argv[1]);
93 if (transaction && tdb_transaction_start(tdb))
94 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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)
111 if (transaction && tdb_transaction_start(tdb))
112 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
114 /* Finding 1000 records. */
115 printf("Finding %u records: ", num); fflush(stdout);
116 gettimeofday(&start, NULL);
117 for (i = 0; i < num; i++) {
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);
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)
132 if (transaction && tdb_transaction_start(tdb))
133 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
135 /* Missing 1000 records. */
136 printf("Missing %u records: ", num); fflush(stdout);
137 gettimeofday(&start, NULL);
138 for (i = num; i < num*2; i++) {
140 dptr = (int *)tdb_fetch(tdb, key).dptr;
142 errx(1, "Fetching key %u in tdb gave %u", i, *dptr);
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)
152 if (transaction && tdb_transaction_start(tdb))
153 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
155 /* Traverse 1000 records. */
156 printf("Traversing %u records: ", num); fflush(stdout);
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)
171 if (transaction && tdb_transaction_start(tdb))
172 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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));
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)
191 if (transaction && tdb_transaction_start(tdb))
192 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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));
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)
211 if (transaction && tdb_transaction_start(tdb))
212 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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)
229 if (transaction && tdb_transaction_start(tdb))
230 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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));
241 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
242 errx(1, "Inserting key %u in tdb: %s",
243 i, tdb_errorstr(tdb));
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());