]> mj.ucw.cz Git - libucw.git/blob - lib/db-test.c
Polished the introductory comments in sorter.h.
[libucw.git] / lib / db-test.c
1 /*
2  *      UCW Library -- Database Manager -- Tests and Benchmarks
3  *
4  *      (c) 1999 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #if 1
11 #include "lib/db.c"
12 #define NAME "SDBM"
13 #else
14 #include "lib/db-emul.c"
15 #define NAME "GDBM"
16 #endif
17
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <stdarg.h>
21 #include <sys/stat.h>
22
23 static struct sdbm_options opts = {
24   flags: SDBM_CREAT | SDBM_WRITE,
25   name: "db.test",
26   page_order: 10,
27   cache_size: 1024,
28   key_size: -1,
29   val_size: -1
30 };
31
32 static struct sdbm *d;
33 static int key_min, key_max;            /* min<0 -> URL distribution */
34 static int val_min, val_max;
35 static int num_keys;                    /* Number of distinct keys */
36 static int verbose;
37
38 static void
39 help(void)
40 {
41   printf("Usage: dbtest [<options>] <commands>\n\
42 \n\
43 Options:\n\
44 -c<n>           Use cache of <n> pages\n\
45 -p<n>           Use pages of order <n>\n\
46 -k<n>           Use key size <n>\n\
47 -k<m>-<n>       Use key size uniformly distributed between <m> and <n>\n\
48 -kU             Use keys with URL distribution\n\
49 -n<n>           Number of distinct keys\n\
50 -d<m>[-<n>]     Use specified value size (see -k<m>-<n>)\n\
51 -t              Perform the tests on an existing database file\n\
52 -v              Be verbose\n\
53 -s              Turn on synchronous mode\n\
54 -S              Turn on supersynchronous mode\n\
55 -F              Turn on fast mode\n\
56 \n\
57 Commands:\n\
58 c               Fill database\n\
59 r               Rewrite database\n\
60 f[<p>%%][<n>]   Find <n> records with probability of success <p>%% (default=100)\n\
61 F[<p>%%][<n>]   Find, but don't fetch values\n\
62 d               Delete records\n\
63 w               Walk database\n\
64 W               Walk, but don't fetch values\n\
65 ");
66   exit(0);
67 }
68
69 static uns
70 krand(uns kn)
71 {
72   return kn * 2000000011;
73 }
74
75 static uns
76 gen_url_size(uns rnd)
77 {
78   uns l, m, r;
79   static uns utable[] = {
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 22, 108, 245, 481, 979, 3992, 7648, 13110, 19946, 27256, 34993, 43222, 52859, 64563,
81 80626, 117521, 147685, 188364, 233174, 290177, 347132, 407231, 465787, 540931, 628601, 710246, 808671, 922737, 1025691, 1138303,
82 1238802, 1344390, 1443843, 1533207, 1636494, 1739082, 1826911, 1910725, 1993940, 2094365, 2188987, 2267827, 2350190, 2441980,
83 2520713, 2593654, 2668632, 2736009, 2808356, 2889682, 2959300, 3017945, 3086488, 3146032, 3204818, 3251897, 3307001, 3349388,
84 3392798, 3433429, 3476765, 3529107, 3556884, 3585120, 3633005, 3677697, 3699561, 3716660, 3739823, 3765154, 3795096, 3821184,
85 3858117, 3908757, 3929095, 3943264, 3957033, 3969588, 3983441, 3994630, 4005413, 4028890, 4039678, 4058007, 4071906, 4087029,
86 4094233, 4105259, 4111603, 4120338, 4127364, 4133983, 4140310, 4144843, 4150565, 4155974, 4165132, 4170648, 4176811, 4187118,
87 4190866, 4199051, 4206686, 4216122, 4226109, 4233721, 4254123, 4261792, 4270396, 4276650, 4282932, 4291738, 4295932, 4299370,
88 4304011, 4307098, 4311866, 4318168, 4325730, 4329774, 4332946, 4336305, 4339770, 4345237, 4349038, 4356129, 4362872, 4366542,
89 4371077, 4374524, 4376733, 4378794, 4380652, 4382340, 4383552, 4385952, 4386914, 4393123, 4394106, 4395142, 4396593, 4399112,
90 4399909, 4401015, 4401780, 4402616, 4403454, 4404481, 4405231, 4405947, 4406886, 4408364, 4409159, 4409982, 4410872, 4412010,
91 4413341, 4414161, 4415673, 4417135, 4418032, 4419117, 4419952, 4420677, 4421387, 4421940, 4422469, 4423210, 4423696, 4424274,
92 4424982, 4425665, 4426363, 4427018, 4427969, 4428992, 4429791, 4430804, 4432601, 4433440, 4434157, 4434967, 4436280, 4439784,
93 4444255, 4445544, 4446416, 4447620, 4449638, 4453004, 4455470, 4456982, 4457956, 4458617, 4459538, 4460007, 4460377, 4460768,
94 4461291, 4461520, 4461678, 4461911, 4462063, 4462239, 4462405, 4462607, 4462666, 4462801, 4462919, 4463108, 4463230, 4463438,
95 4463530, 4463698, 4463779, 4463908, 4463991, 4464138, 4464188, 4464391, 4464580, 4464868, 4464980, 4465174, 4465255, 4465473,
96 4465529, 4465681, 4465746, 4465916, 4465983, 4466171, 4466248, 4466430, 4466560, 4466751, 4466930, 4467807, 4468847, 4469940,
97 4470344, 4470662, 4470716, 4471120, 4471389, 4471814, 4472141, 4472545, 4472687, 4473051, 4473253, 4473603, 4473757, 4474065,
98 4474125, 4474354, 4474428, 4474655, 4474705, 4474841, 4474858, 4475133, 4475201, 4475327, 4475367, 4475482, 4475533, 4475576,
99 4475586, 4475616, 4475637, 4475659, 4475696, 4475736, 4475775, 4475794, 4476156, 4476711, 4477004, 4477133, 4477189, 4477676,
100 4477831, 4477900, 4477973, 4477994, 4478011, 4478040, 4478063, 4478085, 4478468, 4478715, 4479515, 4480034, 4481804, 4483259,
101 4483866, 4484202, 4484932, 4485693, 4486184, 4486549, 4486869, 4487405, 4487639, 4487845, 4488086, 4488256, 4488505, 4488714,
102 4492669, 4496233, 4497738, 4498122, 4498653, 4499862, 4501169, 4501627, 4501673, 4501811, 4502182, 4502475, 4502533, 4502542,
103 4502548, 4502733, 4503389, 4504381, 4505070, 4505378, 4505814, 4506031, 4506336, 4506642, 4506845, 4506971, 4506986, 4507016,
104 4507051, 4507098, 4507107, 4507114, 4507139, 4507478, 4507643, 4507674, 4507694, 4507814, 4507894, 4507904, 4507929, 4507989,
105 4508023, 4508047, 4508053, 4508063, 4508075, 4508092, 4508104, 4508113, 4508239, 4508285, 4508324, 4508335, 4508340, 4508378,
106 4508405, 4508419, 4508436, 4508449, 4508470, 4508488, 4508515, 4508541, 4508564, 4508570, 4508584, 4508594, 4508607, 4508634,
107 4508652, 4508665, 4508673, 4508692, 4508704, 4508742, 4508755, 4508773, 4508788, 4508798, 4508832, 4508869, 4508885, 4508905,
108 4508915, 4508947, 4508956, 4509061, 4509070, 4509357, 4509368, 4509380, 4509393, 4509401, 4509412, 4509426, 4509438, 4509451,
109 4509461, 4509473, 4509489, 4509498, 4509512, 4509537, 4509568, 4509582, 4509621, 4509629, 4509747, 4509766, 4509776, 4509795,
110 4509802, 4509813, 4509822, 4509829, 4509834, 4509844, 4509854, 4509863, 4509868, 4509875, 4509886, 4509898, 4509908, 4509920,
111 4509932, 4509941, 4509949, 4509955, 4509967, 4509972, 4509979, 4509987, 4509999, 4510002, 4510010, 4510014, 4510018, 4510025,
112 4510028, 4510049, 4510055, 4510061, 4510068, 4510079, 4510085, 4510091, 4510098, 4510102, 4510104, 4510110, 4510121, 4510128,
113 4510132, 4510138, 4510144, 4510145, 4510153, 4510161, 4510174, 4510196, 4510199, 4510208, 4510209, 4510212, 4510216, 4510217,
114 4510219, 4510222, 4510228, 4510231, 4510236, 4510241, 4510245, 4510248, 4510250, 4510254, 4510255, 4510261, 4510262, 4510266,
115 4510266, 4510271, 4510285, 4510287, 4510291, 4510295, 4510303, 4510306, 4510308, 4510310, 4510314, 4510319, 4510320, 4510324,
116 4510328, 4510333, 4510333, 4510336, 4510340, 4510342, 4510348, 4510353, 4510359, 4510362, 4510365, 4510371, 4510373, 4510375,
117 4510378, 4510380, 4510385, 4510389, 4510391, 4510391, 4510394, 4510396, 4510397, 4510398, 4510400, 4510403, 4510406, 4510407,
118 4510408, 4510409, 4510411, 4510413, 4510417, 4510417, 4510419, 4510422, 4510426, 4510427, 4510430, 4510435, 4510437, 4510439,
119 4510440, 4510442, 4510442, 4510446, 4510447, 4510448, 4510450, 4510451, 4510451, 4510453, 4510454, 4510455, 4510457, 4510460,
120 4510460, 4510460, 4510462, 4510463, 4510466, 4510468, 4510472, 4510475, 4510480, 4510482, 4510483, 4510486, 4510488, 4510492,
121 4510494, 4510497, 4510497, 4510499, 4510503, 4510505, 4510506, 4510507, 4510509, 4510512, 4510514, 4510527, 4510551, 4510553,
122 4510554, 4510555, 4510556, 4510558, 4510561, 4510562, 4510566, 4510567, 4510568, 4510570, 4510573, 4510574, 4510586, 4510603,
123 4510605, 4510607, 4510610, 4510610, 4510613, 4510613, 4510614, 4510614, 4510615, 4510616, 4510616, 4510620, 4510622, 4510623,
124 4510624, 4510627, 4510628, 4510630, 4510631, 4510632, 4510634, 4510634, 4510634, 4510636, 4510636, 4510639, 4510639, 4510640,
125 4510643, 4510647, 4510649, 4510650, 4510653, 4510653, 4510653, 4510653, 4510656, 4510659, 4510661, 4510664, 4510665, 4510669,
126 4510672, 4510673, 4510674, 4510675, 4510680, 4510683, 4510684, 4510686, 4510687, 4510690, 4510691, 4510693, 4510693, 4510697,
127 4510699, 4510700, 4510703, 4510704, 4510709, 4510711, 4510713, 4510713, 4510720, 4510720, 4510722, 4510724, 4510727, 4510729,
128 4510735, 4510735, 4510738, 4510740, 4510744, 4510745, 4510746, 4510748, 4510754, 4510756, 4510758, 4510761, 4510764, 4510766,
129 4510768, 4510768, 4510770, 4510770, 4510772, 4510774, 4510775, 4510775, 4510775, 4510776, 4510777, 4510780, 4510782, 4510783,
130 4510785, 4510786, 4510788, 4510789, 4510791, 4510793, 4510793, 4510793, 4510795, 4510795, 4510799, 4510803, 4510804, 4510804,
131 4510804, 4510805, 4510807, 4510809, 4510811, 4510811, 4510813, 4510815, 4510815, 4510816, 4510819, 4510820, 4510824, 4510827,
132 4510829, 4510829, 4510830, 4510833, 4510835, 4510837, 4510838, 4510838, 4510839, 4510840, 4510840, 4510842, 4510842, 4510843,
133 4510845, 4510845, 4510845, 4510847, 4510848, 4510848, 4510848, 4510850, 4510853, 4510855, 4510857, 4510859, 4510861, 4510862,
134 4510864, 4510865, 4510865, 4510865, 4510869, 4510869, 4510869, 4510869, 4510869, 4510870, 4510870, 4510872, 4510872, 4510873,
135 4510874, 4510875, 4510875, 4510877, 4510879, 4510879, 4510879, 4510879, 4510880, 4510881, 4510882, 4510883, 4510884, 4510885,
136 4510886, 4510887, 4510890, 4510890, 4510891, 4510892, 4510892, 4510893, 4510893, 4510895, 4510895, 4510896, 4510897, 4510899,
137 4510901, 4510901, 4510901, 4510902, 4510903, 4510903, 4510903, 4510905, 4510905, 4510906, 4510906, 4510907, 4510907, 4510909,
138 4510910, 4510911, 4510911, 4510911, 4510913, 4510913, 4510914, 4510914, 4510914, 4510915, 4510916, 4510918, 4510918, 4510919,
139 4510919, 4510919, 4510920, 4510921, 4510922, 4510923, 4510924, 4510924, 4510924, 4510924, 4510926, 4510927, 4510928, 4510928,
140 4510928, 4510928, 4510928, 4510930, 4510933, 4510935, 4510935, 4510935, 4510935, 4510935, 4510936, 4510938, 4510947, 4510966,
141 4510967, 4510969, 4510973, 4510973, 4510974, 4510974, 4510974, 4510974, 4510974, 4510974, 4510975, 4510976, 4510976, 4510976,
142 4510976, 4510976, 4510976, 4510976, 4510977, 4510979, 4510979, 4510979, 4510979, 4510979, 4510979, 4510980, 4510980, 4510980,
143 4510980, 4510981, 4510981, 4510981, 4510982, 4510982, 4510982, 4510982, 4510982, 4510982, 4510982, 4510983, 4510983, 4510984,
144 4510984, 4510984, 4510984, 4510984, 4510985, 4510985, 4510985, 4510985, 4510987, 4510987, 4510987, 4510988, 4510988, 4510989,
145 4510989, 4510989, 4510989, 4510989, 4510990, 4510990, 4510990, 4510990, 4510990, 4510990, 4510990, 4510991, 4510991, 4510991,
146 4510991, 4510991, 4510991, 4510991, 4510992, 4510992, 4510992, 4510992, 4510992, 4510992, 4510992, 4510993, 4510993, 4510993,
147 4510994, 4510994, 4510994, 4510994, 4510995, 4510995, 4510996, 4510997, 4510998, 4510999, 4510999, 4511000, 4511000, 4511001,
148 4511001, 4511002, 4511002, 4511002, 4511003, 4511004, 4511004, 4511004, 4511004, 4511005, 4511006, 4511008, 4511008, 4511008,
149 4511009, 4511009, 4511009, 4511009, 4511010, 4511011, 4511011, 4511012, 4511012, 4511012, 4511012, 4511013, 4511013, 4511014,
150 4511014, 4511014, 4511014, 4511015, 4511018, 4511018, 4511018, 4511018, 4511018, 4511018, 4511018, 4511020, 4511020, 4511020,
151 4511020, 4511020, 4511020, 4511020, 4511021, 4511021, 4511021, 4511021, 4511021, 4511021, 4511021, 4511021, 4511021, 4511021,
152 4511021
153   };
154
155   rnd %= utable[1024];
156   l = 0; r = 1023;
157   while (l < r)
158     {
159       m = (l+r)/2;
160       if (utable[m] == rnd)
161         return m;
162       if (utable[m] >= rnd)
163         r = m - 1;
164       else
165         l = m + 1;
166     }
167   return l;
168 }
169
170 static uns
171 gen_size(uns min, uns max, uns rnd)
172 {
173   if (min == max)
174     return min;
175   else
176     return min + rnd % (max - min + 1);
177 }
178
179 static void
180 gen_random(byte *buf, uns size, uns kn)
181 {
182   kn = (kn + 0x36221057) ^ (kn << 24) ^ (kn << 15);
183   while (size--)
184     {
185       *buf++ = kn >> 24;
186       kn = kn*257 + 17;
187     }
188 }
189
190 static int
191 keygen(byte *buf, uns kn)
192 {
193   uns size, rnd;
194
195   rnd = krand(kn);
196   if (key_min < 0)
197     size = gen_url_size(rnd);
198   else
199     size = gen_size(key_min, key_max, rnd);
200   *buf++ = kn >> 24;
201   *buf++ = kn >> 16;
202   *buf++ = kn >> 8;
203   *buf++ = kn;
204   if (size < 4)
205     return 4;
206   gen_random(buf, size-4, kn);
207   return size;
208 }
209
210 static int
211 valgen(byte *buf, uns kn)
212 {
213   uns size = gen_size(val_min, val_max, krand(kn));
214   gen_random(buf, size, kn);
215   return size;
216 }
217
218 static uns
219 keydec(byte *buf)
220 {
221   return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
222 }
223
224 static void
225 verb(char *msg, ...)
226 {
227   int cat = 1;
228   va_list args;
229
230   va_start(args, msg);
231   if (msg[0] == '^' && msg[1])
232     {
233       cat = msg[1] - '0';
234       msg += 2;
235     }
236   if (verbose >= cat)
237     vfprintf(stderr, msg, args);
238   va_end(args);
239 }
240
241 static void
242 parse_size(int *min, int *max, char *c)
243 {
244   char *d;
245
246   if ((d = strchr(c, '-')))
247     {
248       *d++ = 0;
249       *min = atol(c);
250       *max = atol(d);
251     }
252   else
253     *min = *max = atol(c);
254 }
255
256 #define PROGRESS(i) if ((verbose > 2) || (verbose > 1 && !(i & 1023))) fprintf(stderr, "%d\r", i)
257
258 int main(int argc, char **argv)
259 {
260   int c, i, j, k, l, m;
261   byte kb[2048], vb[2048], vb2[2048];
262   uns ks, vs, vs2, perc, cnt;
263   char *ch;
264   int dont_delete = 0;
265   timestamp_t timer;
266
267   log_init("dbtest");
268   setvbuf(stdout, NULL, _IONBF, 0);
269   setvbuf(stderr, NULL, _IONBF, 0);
270   while ((c = getopt(argc, argv, "c:p:k:n:d:vsStF")) >= 0)
271     switch (c)
272       {
273       case 'c':
274         opts.cache_size = atol(optarg);
275         break;
276       case 'p':
277         opts.page_order = atol(optarg);
278         break;
279       case 'k':
280         if (!strcmp(optarg, "U"))
281           key_min = key_max = -1;
282         else
283           parse_size(&key_min, &key_max, optarg);
284         break;
285       case 'n':
286         num_keys = atol(optarg);
287         break;
288       case 'd':
289         parse_size(&val_min, &val_max, optarg);
290         break;
291       case 'v':
292         verbose++;
293         break;
294       case 's':
295         opts.flags |= SDBM_SYNC;
296         break;
297       case 'S':
298         opts.flags |= SDBM_SYNC | SDBM_FSYNC;
299         break;
300       case 'F':
301         opts.flags |= SDBM_FAST;
302         break;
303       case 't':
304         dont_delete = 1;
305         break;
306       default:
307         help();
308       }
309
310   if (key_min >= 0 && key_min < 4)
311     key_min = key_max = 4;
312   if (key_min == key_max && key_min >= 0)
313     opts.key_size = key_min;
314   if (val_min == val_max)
315     opts.val_size = val_min;
316   if (!num_keys)
317     die("Number of keys not given");
318
319   printf(NAME " benchmark: %d records, keys ", num_keys);
320   if (key_min < 0)
321     printf("<URL>");
322   else
323     printf("%d-%d", key_min, key_max);
324   printf(", values %d-%d, page size %d, cache %d pages\n", val_min, val_max, 1 << opts.page_order, opts.cache_size);
325
326   verb("OPEN(%s, key=%d, val=%d, cache=%d, pgorder=%d)\n", opts.name, opts.key_size, opts.val_size,
327        opts.cache_size, opts.page_order);
328   if (!dont_delete)
329     unlink(opts.name);
330   d = sdbm_open(&opts);
331   if (!d)
332     die("open failed: %m");
333
334   while (optind < argc)
335     {
336       char *o = argv[optind++];
337       init_timer(&timer);
338       switch (*o)
339         {
340         case 'c':
341           printf("create %d: ", num_keys);
342           for(i=0; i<num_keys; i++)
343             {
344               PROGRESS(i);
345               ks = keygen(kb, i);
346               vs = valgen(vb, i);
347               if (sdbm_store(d, kb, ks, vb, vs) != 1) die("store failed");
348             }
349           break;
350         case 'r':
351           printf("rewrite %d: ", num_keys);
352           for(i=0; i<num_keys; i++)
353             {
354               PROGRESS(i);
355               ks = keygen(kb, i);
356               vs = valgen(vb, i);
357               if (sdbm_replace(d, kb, ks, vb, vs) != 1) die("replace failed");
358             }
359           break;
360         case 'f':
361         case 'F':
362           c = (*o++ == 'f');
363           if ((ch = strchr(o, '%')))
364             {
365               *ch++ = 0;
366               perc = atol(o);
367             }
368           else
369             {
370               ch = o;
371               perc = 100;
372             }
373           cnt = atol(ch);
374           if (!cnt)
375             {
376               cnt = num_keys;
377               m = (perc == 100);
378             }
379           else
380             m = 0;
381           printf("%s fetch %d (%d%% success, with%s values): ", (m ? "sequential" : "random"), cnt, perc, (c ? "" : "out"));
382           i = -1;
383           while (cnt--)
384             {
385               if (m)
386                 i++;
387               else
388                 i = random_max(num_keys) + ((random_max(100) < perc) ? 0 : num_keys);
389               PROGRESS(i);
390               ks = keygen(kb, i);
391               if (c)
392                 {
393                   vs2 = sizeof(vb2);
394                   j = sdbm_fetch(d, kb, ks, vb2, &vs2);
395                 }
396               else
397                 j = sdbm_fetch(d, kb, ks, NULL, NULL);
398               if (j < 0)
399                 die("fetch: error %d", j);
400               if ((i < num_keys) != j)
401                 die("fetch mismatch at key %d, res %d", i, j);
402               if (c && j)
403                 {
404                   vs = valgen(vb, i);
405                   if (vs != vs2 || memcmp(vb, vb2, vs))
406                     die("fetch data mismatch at key %d: %d,%d", i, vs, vs2);
407                 }
408             }
409           break;
410         case 'd':
411           printf("delete %d: ", num_keys);
412           for(i=0; i<num_keys; i++)
413             {
414               PROGRESS(i);
415               ks = keygen(kb, i);
416               if (sdbm_delete(d, kb, ks) != 1) die("delete failed");
417             }
418           break;
419         case 'w':
420         case 'W':
421           c = (*o == 'w');
422           i = k = l = m = 0;
423           printf("walk %d (with%s keys): ", num_keys, (c ? "" : "out"));
424           sdbm_rewind(d);
425           for(;;)
426             {
427               ks = sizeof(kb);
428               vs = sizeof(vb);
429               if (c)
430                 j = sdbm_get_next(d, kb, &ks, vb, &vs);
431               else
432                 j = sdbm_get_next(d, kb, &ks, NULL, NULL);
433               if (!j)
434                 break;
435               if (ks < 4)
436                 die("get_next: too short");
437               i = keydec(kb);
438               if (i < 0 || i >= num_keys)
439                 die("get_next: %d out of range", i);
440               PROGRESS(i);
441               vs2 = keygen(vb2, i);
442               if (ks != vs2 || memcmp(kb, vb2, ks))
443                 die("get_next: key mismatch at %d", i);
444               if (c)
445                 {
446                   vs2 = valgen(vb2, i);
447                   if (vs != vs2 || memcmp(vb, vb2, vs))
448                     die("get_next: data mismatch at %d", i);
449                 }
450               l += k;
451               m += i;
452               k++;
453             }
454           if (k != num_keys)
455             die("fetch: wrong # of keys: %d != %d", k, num_keys);
456           if (l != m)
457             die("fetch: wrong checksum: %d != %d", l, m);
458           break;
459         default:
460           help();
461         }
462       sdbm_sync(d);
463       printf("%d ms\n", get_timer(&timer));
464     }
465
466   verb("CLOSE\n");
467   sdbm_close(d);
468
469   {
470     struct stat st;
471     if (stat(opts.name, &st)) die("stat: %m");
472     printf("file size: %d bytes\n", (int) st.st_size);
473   }
474   return 0;
475 }