1 /* Simple speed test for TDB */
13 #include <ccan/tdb/tdb.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;
51 struct tdb_context *tdb;
52 struct timeval start, stop;
53 bool transaction = false;
55 if (argv[1] && strcmp(argv[1], "--internal") == 0) {
61 if (argv[1] && strcmp(argv[1], "--transaction") == 0) {
67 tdb = tdb_open("/tmp/speed.tdb", 100003, flags, O_RDWR|O_CREAT|O_TRUNC,
70 err(1, "Opening /tmp/speed.tdb");
72 key.dptr = (void *)&i;
73 key.dsize = sizeof(i);
83 stopat = atoi(argv[1]);
88 if (transaction && tdb_transaction_start(tdb))
89 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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)
106 if (transaction && tdb_transaction_start(tdb))
107 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
109 /* Finding 1000 records. */
110 printf("Finding %u records: ", num); fflush(stdout);
111 gettimeofday(&start, NULL);
112 for (i = 0; i < num; i++) {
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);
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)
127 if (transaction && tdb_transaction_start(tdb))
128 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
130 /* Missing 1000 records. */
131 printf("Missing %u records: ", num); fflush(stdout);
132 gettimeofday(&start, NULL);
133 for (i = num; i < num*2; i++) {
135 dptr = (int *)tdb_fetch(tdb, key).dptr;
137 errx(1, "Fetching key %u in tdb gave %u", i, *dptr);
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)
147 if (transaction && tdb_transaction_start(tdb))
148 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
150 /* Traverse 1000 records. */
151 printf("Traversing %u records: ", num); fflush(stdout);
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)
166 if (transaction && tdb_transaction_start(tdb))
167 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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));
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)
186 if (transaction && tdb_transaction_start(tdb))
187 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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));
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)
206 if (transaction && tdb_transaction_start(tdb))
207 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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)
224 if (transaction && tdb_transaction_start(tdb))
225 errx(1, "starting transaction: %s", tdb_errorstr(tdb));
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));
236 if (tdb_store(tdb, key, data, TDB_INSERT) != 0)
237 errx(1, "Inserting key %u in tdb: %s",
238 i, tdb_errorstr(tdb));
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());