librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/gebeck_regimport.git] / lib / ntdb / tools / speed.c
blob8928d8c67a37bc933aad99fe9ff5189b266f2f66
1 /* Simple speed test for NTDB */
2 #include <ccan/err/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 "ntdb.h"
15 /* Nanoseconds per operation */
16 static size_t normalize(const struct timeval *start,
17 const struct timeval *stop,
18 unsigned int num)
20 struct timeval diff;
22 timersub(stop, start, &diff);
24 /* Floating point is more accurate here. */
25 return (double)(diff.tv_sec * 1000000 + diff.tv_usec)
26 / num * 1000;
29 static size_t file_size(void)
31 struct stat st;
33 if (stat("/tmp/speed.ntdb", &st) != 0)
34 return -1;
35 return st.st_size;
38 static int count_record(struct ntdb_context *ntdb,
39 NTDB_DATA key, NTDB_DATA data, void *p)
41 int *total = p;
42 *total += *(int *)data.dptr;
43 return 0;
46 static void dump_and_clear_stats(struct ntdb_context **ntdb,
47 int flags,
48 union ntdb_attribute *attr)
50 union ntdb_attribute stats;
51 enum NTDB_ERROR ecode;
53 stats.base.attr = NTDB_ATTRIBUTE_STATS;
54 stats.stats.size = sizeof(stats.stats);
55 ecode = ntdb_get_attribute(*ntdb, &stats);
56 if (ecode != NTDB_SUCCESS)
57 errx(1, "Getting stats: %s", ntdb_errorstr(ecode));
59 printf("allocs = %llu\n",
60 (unsigned long long)stats.stats.allocs);
61 printf(" alloc_subhash = %llu\n",
62 (unsigned long long)stats.stats.alloc_subhash);
63 printf(" alloc_chain = %llu\n",
64 (unsigned long long)stats.stats.alloc_chain);
65 printf(" alloc_bucket_exact = %llu\n",
66 (unsigned long long)stats.stats.alloc_bucket_exact);
67 printf(" alloc_bucket_max = %llu\n",
68 (unsigned long long)stats.stats.alloc_bucket_max);
69 printf(" alloc_leftover = %llu\n",
70 (unsigned long long)stats.stats.alloc_leftover);
71 printf(" alloc_coalesce_tried = %llu\n",
72 (unsigned long long)stats.stats.alloc_coalesce_tried);
73 printf(" alloc_coalesce_iterate_clash = %llu\n",
74 (unsigned long long)stats.stats.alloc_coalesce_iterate_clash);
75 printf(" alloc_coalesce_lockfail = %llu\n",
76 (unsigned long long)stats.stats.alloc_coalesce_lockfail);
77 printf(" alloc_coalesce_race = %llu\n",
78 (unsigned long long)stats.stats.alloc_coalesce_race);
79 printf(" alloc_coalesce_succeeded = %llu\n",
80 (unsigned long long)stats.stats.alloc_coalesce_succeeded);
81 printf(" alloc_coalesce_num_merged = %llu\n",
82 (unsigned long long)stats.stats.alloc_coalesce_num_merged);
83 printf("compares = %llu\n",
84 (unsigned long long)stats.stats.compares);
85 printf(" compare_wrong_offsetbits = %llu\n",
86 (unsigned long long)stats.stats.compare_wrong_offsetbits);
87 printf(" compare_wrong_keylen = %llu\n",
88 (unsigned long long)stats.stats.compare_wrong_keylen);
89 printf(" compare_wrong_rechash = %llu\n",
90 (unsigned long long)stats.stats.compare_wrong_rechash);
91 printf(" compare_wrong_keycmp = %llu\n",
92 (unsigned long long)stats.stats.compare_wrong_keycmp);
93 printf("transactions = %llu\n",
94 (unsigned long long)stats.stats.transactions);
95 printf(" transaction_cancel = %llu\n",
96 (unsigned long long)stats.stats.transaction_cancel);
97 printf(" transaction_nest = %llu\n",
98 (unsigned long long)stats.stats.transaction_nest);
99 printf(" transaction_expand_file = %llu\n",
100 (unsigned long long)stats.stats.transaction_expand_file);
101 printf(" transaction_read_direct = %llu\n",
102 (unsigned long long)stats.stats.transaction_read_direct);
103 printf(" transaction_read_direct_fail = %llu\n",
104 (unsigned long long)stats.stats.transaction_read_direct_fail);
105 printf(" transaction_write_direct = %llu\n",
106 (unsigned long long)stats.stats.transaction_write_direct);
107 printf(" transaction_write_direct_fail = %llu\n",
108 (unsigned long long)stats.stats.transaction_write_direct_fail);
109 printf("expands = %llu\n",
110 (unsigned long long)stats.stats.expands);
111 printf("frees = %llu\n",
112 (unsigned long long)stats.stats.frees);
113 printf("locks = %llu\n",
114 (unsigned long long)stats.stats.locks);
115 printf(" lock_lowlevel = %llu\n",
116 (unsigned long long)stats.stats.lock_lowlevel);
117 printf(" lock_nonblock = %llu\n",
118 (unsigned long long)stats.stats.lock_nonblock);
119 printf(" lock_nonblock_fail = %llu\n",
120 (unsigned long long)stats.stats.lock_nonblock_fail);
122 /* Now clear. */
123 ntdb_close(*ntdb);
124 *ntdb = ntdb_open("/tmp/speed.ntdb", flags, O_RDWR, 0, attr);
127 static void ntdb_log(struct ntdb_context *ntdb,
128 enum ntdb_log_level level,
129 enum NTDB_ERROR ecode,
130 const char *message,
131 void *data)
133 fprintf(stderr, "ntdb:%s:%s:%s\n",
134 ntdb_name(ntdb), ntdb_errorstr(ecode), message);
137 int main(int argc, char *argv[])
139 unsigned int i, j, num = 1000, stage = 0, stopat = -1;
140 int flags = NTDB_DEFAULT;
141 bool transaction = false, summary = false;
142 NTDB_DATA key, data;
143 struct ntdb_context *ntdb;
144 struct timeval start, stop;
145 union ntdb_attribute seed, log;
146 bool do_stats = false;
147 enum NTDB_ERROR ecode;
149 /* Try to keep benchmarks even. */
150 seed.base.attr = NTDB_ATTRIBUTE_SEED;
151 seed.base.next = NULL;
152 seed.seed.seed = 0;
154 log.base.attr = NTDB_ATTRIBUTE_LOG;
155 log.base.next = &seed;
156 log.log.fn = ntdb_log;
158 if (argv[1] && strcmp(argv[1], "--internal") == 0) {
159 flags = NTDB_INTERNAL;
160 argc--;
161 argv++;
163 if (argv[1] && strcmp(argv[1], "--transaction") == 0) {
164 transaction = true;
165 argc--;
166 argv++;
168 if (argv[1] && strcmp(argv[1], "--no-sync") == 0) {
169 flags |= NTDB_NOSYNC;
170 argc--;
171 argv++;
173 if (argv[1] && strcmp(argv[1], "--summary") == 0) {
174 summary = true;
175 argc--;
176 argv++;
178 if (argv[1] && strcmp(argv[1], "--stats") == 0) {
179 do_stats = true;
180 argc--;
181 argv++;
184 ntdb = ntdb_open("/tmp/speed.ntdb", flags, O_RDWR|O_CREAT|O_TRUNC,
185 0600, &log);
186 if (!ntdb)
187 err(1, "Opening /tmp/speed.ntdb");
189 key.dptr = (void *)&i;
190 key.dsize = sizeof(i);
191 data = key;
193 if (argv[1]) {
194 num = atoi(argv[1]);
195 argv++;
196 argc--;
199 if (argv[1]) {
200 stopat = atoi(argv[1]);
201 argv++;
202 argc--;
205 /* Add 1000 records. */
206 printf("Adding %u records: ", num); fflush(stdout);
207 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
208 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
209 gettimeofday(&start, NULL);
210 for (i = 0; i < num; i++)
211 if ((ecode = ntdb_store(ntdb, key, data, NTDB_INSERT)) != 0)
212 errx(1, "Inserting key %u in ntdb: %s",
213 i, ntdb_errorstr(ecode));
214 gettimeofday(&stop, NULL);
215 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
216 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
217 printf(" %zu ns (%zu bytes)\n",
218 normalize(&start, &stop, num), file_size());
220 if (ntdb_check(ntdb, NULL, NULL))
221 errx(1, "ntdb_check failed!");
222 if (summary) {
223 char *sumstr = NULL;
224 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
225 printf("%s\n", sumstr);
226 free(sumstr);
228 if (do_stats)
229 dump_and_clear_stats(&ntdb, flags, &log);
231 if (++stage == stopat)
232 exit(0);
234 /* Finding 1000 records. */
235 printf("Finding %u records: ", num); fflush(stdout);
236 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
237 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
238 gettimeofday(&start, NULL);
239 for (i = 0; i < num; i++) {
240 NTDB_DATA dbuf;
241 if ((ecode = ntdb_fetch(ntdb, key, &dbuf)) != NTDB_SUCCESS
242 || *(int *)dbuf.dptr != i) {
243 errx(1, "Fetching key %u in ntdb gave %u",
244 i, ecode ? ecode : *(int *)dbuf.dptr);
247 gettimeofday(&stop, NULL);
248 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
249 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
250 printf(" %zu ns (%zu bytes)\n",
251 normalize(&start, &stop, num), file_size());
252 if (ntdb_check(ntdb, NULL, NULL))
253 errx(1, "ntdb_check failed!");
254 if (summary) {
255 char *sumstr = NULL;
256 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
257 printf("%s\n", sumstr);
258 free(sumstr);
260 if (do_stats)
261 dump_and_clear_stats(&ntdb, flags, &log);
262 if (++stage == stopat)
263 exit(0);
265 /* Missing 1000 records. */
266 printf("Missing %u records: ", num); fflush(stdout);
267 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
268 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
269 gettimeofday(&start, NULL);
270 for (i = num; i < num*2; i++) {
271 NTDB_DATA dbuf;
272 ecode = ntdb_fetch(ntdb, key, &dbuf);
273 if (ecode != NTDB_ERR_NOEXIST)
274 errx(1, "Fetching key %u in ntdb gave %s",
275 i, ntdb_errorstr(ecode));
277 gettimeofday(&stop, NULL);
278 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
279 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
280 printf(" %zu ns (%zu bytes)\n",
281 normalize(&start, &stop, num), file_size());
282 if (ntdb_check(ntdb, NULL, NULL))
283 errx(1, "ntdb_check failed!");
284 if (summary) {
285 char *sumstr = NULL;
286 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
287 printf("%s\n", sumstr);
288 free(sumstr);
290 if (do_stats)
291 dump_and_clear_stats(&ntdb, flags, &log);
292 if (++stage == stopat)
293 exit(0);
295 /* Traverse 1000 records. */
296 printf("Traversing %u records: ", num); fflush(stdout);
297 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
298 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
299 i = 0;
300 gettimeofday(&start, NULL);
301 if (ntdb_traverse(ntdb, count_record, &i) != num)
302 errx(1, "Traverse returned wrong number of records");
303 if (i != (num - 1) * (num / 2))
304 errx(1, "Traverse tallied to %u", i);
305 gettimeofday(&stop, NULL);
306 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
307 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
308 printf(" %zu ns (%zu bytes)\n",
309 normalize(&start, &stop, num), file_size());
310 if (ntdb_check(ntdb, NULL, NULL))
311 errx(1, "ntdb_check failed!");
312 if (summary) {
313 char *sumstr = NULL;
314 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
315 printf("%s\n", sumstr);
316 free(sumstr);
318 if (do_stats)
319 dump_and_clear_stats(&ntdb, flags, &log);
320 if (++stage == stopat)
321 exit(0);
323 /* Delete 1000 records (not in order). */
324 printf("Deleting %u records: ", num); fflush(stdout);
325 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
326 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
327 gettimeofday(&start, NULL);
328 for (j = 0; j < num; j++) {
329 i = (j + 100003) % num;
330 if ((ecode = ntdb_delete(ntdb, key)) != NTDB_SUCCESS)
331 errx(1, "Deleting key %u in ntdb: %s",
332 i, ntdb_errorstr(ecode));
334 gettimeofday(&stop, NULL);
335 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
336 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
337 printf(" %zu ns (%zu bytes)\n",
338 normalize(&start, &stop, num), file_size());
339 if (ntdb_check(ntdb, NULL, NULL))
340 errx(1, "ntdb_check failed!");
341 if (summary) {
342 char *sumstr = NULL;
343 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
344 printf("%s\n", sumstr);
345 free(sumstr);
347 if (do_stats)
348 dump_and_clear_stats(&ntdb, flags, &log);
349 if (++stage == stopat)
350 exit(0);
352 /* Re-add 1000 records (not in order). */
353 printf("Re-adding %u records: ", num); fflush(stdout);
354 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
355 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
356 gettimeofday(&start, NULL);
357 for (j = 0; j < num; j++) {
358 i = (j + 100003) % num;
359 if ((ecode = ntdb_store(ntdb, key, data, NTDB_INSERT)) != 0)
360 errx(1, "Inserting key %u in ntdb: %s",
361 i, ntdb_errorstr(ecode));
363 gettimeofday(&stop, NULL);
364 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
365 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
366 printf(" %zu ns (%zu bytes)\n",
367 normalize(&start, &stop, num), file_size());
368 if (ntdb_check(ntdb, NULL, NULL))
369 errx(1, "ntdb_check failed!");
370 if (summary) {
371 char *sumstr = NULL;
372 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
373 printf("%s\n", sumstr);
374 free(sumstr);
376 if (do_stats)
377 dump_and_clear_stats(&ntdb, flags, &log);
378 if (++stage == stopat)
379 exit(0);
381 /* Append 1000 records. */
382 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
383 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
384 printf("Appending %u records: ", num); fflush(stdout);
385 gettimeofday(&start, NULL);
386 for (i = 0; i < num; i++)
387 if ((ecode = ntdb_append(ntdb, key, data)) != NTDB_SUCCESS)
388 errx(1, "Appending key %u in ntdb: %s",
389 i, ntdb_errorstr(ecode));
390 gettimeofday(&stop, NULL);
391 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
392 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
393 printf(" %zu ns (%zu bytes)\n",
394 normalize(&start, &stop, num), file_size());
395 if (ntdb_check(ntdb, NULL, NULL))
396 errx(1, "ntdb_check failed!");
397 if (summary) {
398 char *sumstr = NULL;
399 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
400 printf("%s\n", sumstr);
401 free(sumstr);
403 if (++stage == stopat)
404 exit(0);
406 /* Churn 1000 records: not in order! */
407 if (transaction && (ecode = ntdb_transaction_start(ntdb)))
408 errx(1, "starting transaction: %s", ntdb_errorstr(ecode));
409 printf("Churning %u records: ", num); fflush(stdout);
410 gettimeofday(&start, NULL);
411 for (j = 0; j < num; j++) {
412 i = (j + 1000019) % num;
413 if ((ecode = ntdb_delete(ntdb, key)) != NTDB_SUCCESS)
414 errx(1, "Deleting key %u in ntdb: %s",
415 i, ntdb_errorstr(ecode));
416 i += num;
417 if ((ecode = ntdb_store(ntdb, key, data, NTDB_INSERT)) != 0)
418 errx(1, "Inserting key %u in ntdb: %s",
419 i, ntdb_errorstr(ecode));
421 gettimeofday(&stop, NULL);
422 if (transaction && (ecode = ntdb_transaction_commit(ntdb)))
423 errx(1, "committing transaction: %s", ntdb_errorstr(ecode));
424 printf(" %zu ns (%zu bytes)\n",
425 normalize(&start, &stop, num), file_size());
427 if (ntdb_check(ntdb, NULL, NULL))
428 errx(1, "ntdb_check failed!");
429 if (summary) {
430 char *sumstr = NULL;
431 ntdb_summary(ntdb, NTDB_SUMMARY_HISTOGRAMS, &sumstr);
432 printf("%s\n", sumstr);
433 free(sumstr);
435 if (do_stats)
436 dump_and_clear_stats(&ntdb, flags, &log);
437 if (++stage == stopat)
438 exit(0);
440 return 0;