2 * UCW Library -- Testing the Old Sorter
4 * (c) 2007 Martin Mares <mj@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
11 #include "lib/getopt.h"
13 #include "lib/fastbuf.h"
14 #include "lib/hashfunc.h"
23 /*** Time measurement ***/
36 log(L_INFO, "Test took %.3fs", get_timer() / 1000.);
39 /*** Simple 4-byte integer keys ***/
45 static inline int s1_compare(struct key1 *x, struct key1 *y)
51 #define SORT_KEY struct key1
52 #define SORT_PREFIX(x) s1_##x
54 #define SORT_OUTPUT_FB
59 #include "lib/sorter.h"
62 test_int(int mode, u64 size)
64 uns N = size ? nextprime(MIN(size/4, 0xffff0000)) : 0;
66 log(L_INFO, ">>> Integers (%s, N=%u)", ((char *[]) { "increasing", "decreasing", "random" })[mode], N);
68 struct fastbuf *f = bopen_tmp(65536);
69 for (uns i=0; i<N; i++)
70 bputl(f, (mode==0) ? i : (mode==1) ? N-1-i : ((u64)i * K + 17) % N);
77 SORT_XTRACE(2, "Verifying");
78 for (uns i=0; i<N; i++)
82 die("Discrepancy: %u instead of %u", j, i);
87 /*** Longer records with hashes (similar to Shepherd's index records) ***/
95 static inline int s3_compare(struct key3 *x, struct key3 *y)
97 /* FIXME: Maybe unroll manually? */
98 for (uns i=0; i<4; i++)
99 COMPARE(x->hash[i], y->hash[i]);
103 #define SORT_KEY struct key3
104 #define SORT_PREFIX(x) s3_##x
105 #define SORT_INPUT_FB
106 #define SORT_OUTPUT_FB
110 #include "lib/sorter.h"
113 gen_hash_key(int mode, struct key3 *k, uns i)
116 k->payload[0] = 7*i + 13;
117 k->payload[1] = 13*i + 19;
118 k->payload[2] = 19*i + 7;
123 k->hash[1] = k->payload[0];
124 k->hash[2] = k->payload[1];
125 k->hash[3] = k->payload[2];
129 k->hash[1] = k->payload[0];
130 k->hash[2] = k->payload[1];
131 k->hash[3] = k->payload[2];
134 struct MD5Context ctx;
136 MD5Update(&ctx, (byte*) &k->i, 4);
137 MD5Final((byte*) &k->hash, &ctx);
143 test_hashes(int mode, u64 size)
145 uns N = MIN(size / sizeof(struct key3), 0xffffffff);
146 log(L_INFO, ">>> Hashes (%s, N=%u)", ((char *[]) { "increasing", "decreasing", "random" })[mode], N);
147 struct key3 k, lastk;
149 struct fastbuf *f = bopen_tmp(65536);
151 for (uns i=0; i<N; i++)
153 gen_hash_key(mode, &k, i);
154 hash_sum += k.hash[3];
155 bwrite(f, &k, sizeof(k));
163 SORT_XTRACE(2, "Verifying");
164 for (uns i=0; i<N; i++)
166 int ok = breadb(f, &k, sizeof(k));
168 if (i && s3_compare(&k, &lastk) <= 0)
170 gen_hash_key(mode, &lastk, k.i);
171 if (memcmp(&k, &lastk, sizeof(k)))
173 hash_sum -= k.hash[3];
179 /*** Variable-length records (strings) with and without var-length data ***/
188 static inline int s4_fetch_key(struct fastbuf *f, struct key4 *x)
194 breadb(f, x->s, len);
198 static inline void s4_copy_data(struct fastbuf *i UNUSED, struct fastbuf *f, struct key4 *x)
201 bwrite(f, x->s, x->len);
204 static inline int s4_compare(struct key4 *x, struct key4 *y)
206 uns l = MIN(x->len, y->len);
207 int c = memcmp(x->s, y->s, l);
210 COMPARE(x->len, y->len);
214 static inline byte *s4_fetch_item(struct fastbuf *f UNUSED, struct key4 *x, byte *limit UNUSED)
216 return &x->s[x->len];
219 static inline void s4_store_item(struct fastbuf *f, struct key4 *x)
221 s4_copy_data(NULL, f, x);
224 #define SORT_KEY struct key4
225 #define SORT_PREFIX(x) s4_##x
226 #define SORT_INPUT_FB
227 #define SORT_OUTPUT_FB
230 #include "lib/sorter.h"
232 #define s4b_compare s4_compare
233 #define s4b_fetch_key s4_fetch_key
235 static inline uns s4_data_size(struct key4 *x)
237 return x->len ? (x->s[0] ^ 0xad) : 0;
240 static inline void s4b_copy_data(struct fastbuf *i, struct fastbuf *f, struct key4 *x)
243 bwrite(f, x->s, x->len);
244 bbcopy(i, f, s4_data_size(x));
247 static inline byte *s4b_fetch_item(struct fastbuf *f, struct key4 *x, byte *limit)
249 byte *d = &x->s[x->len];
250 if (d + s4_data_size(x) > limit)
252 breadb(f, d, s4_data_size(x));
253 return d + s4_data_size(x);
256 static inline void s4b_store_item(struct fastbuf *f, struct key4 *x)
259 bwrite(f, x->s, x->len + s4_data_size(x));
262 #define SORT_KEY struct key4
263 #define SORT_PREFIX(x) s4b_##x
264 #define SORT_INPUT_FB
265 #define SORT_OUTPUT_FB
268 #include "lib/sorter.h"
271 gen_key4(struct key4 *k)
273 k->len = random_max(KEY4_MAX);
274 for (uns i=0; i<k->len; i++)
279 gen_data4(byte *buf, uns len, uns h)
289 test_strings(uns mode, u64 size)
291 uns avg_item_size = KEY4_MAX/2 + 4 + (mode ? 128 : 0);
292 uns N = MIN(size / avg_item_size, 0xffffffff);
293 log(L_INFO, ">>> Strings %s(N=%u)", (mode ? "with data " : ""), N);
296 struct key4 k, lastk;
297 byte buf[256], buf2[256];
300 struct fastbuf *f = bopen_tmp(65536);
301 for (uns i=0; i<N; i++)
304 s4_copy_data(NULL, f, &k);
305 uns h = hash_block(k.s, k.len);
309 gen_data4(buf, s4_data_size(&k), h);
310 bwrite(f, buf, s4_data_size(&k));
316 f = (mode ? s4b_sort : s4_sort)(f);
319 SORT_XTRACE(2, "Verifying");
320 for (uns i=0; i<N; i++)
322 int ok = s4_fetch_key(f, &k);
324 uns h = hash_block(k.s, k.len);
325 if (mode && s4_data_size(&k))
327 ok = breadb(f, buf, s4_data_size(&k));
329 gen_data4(buf2, s4_data_size(&k), h);
330 ASSERT(!memcmp(buf, buf2, s4_data_size(&k)));
332 if (i && s4_compare(&k, &lastk) < 0)
344 run_test(uns i, u64 size)
349 test_int(0, size); break;
351 test_int(1, size); break;
353 test_int(2, size); break;
359 test_hashes(0, size); break;
361 test_hashes(1, size); break;
363 test_hashes(2, size); break;
365 test_strings(0, size); break;
367 test_strings(1, size); break;
373 main(int argc, char **argv)
380 while ((c = cf_getopt(argc, argv, CF_SHORT_OPTS "s:t:v", CF_NO_LONG_OPTS, NULL)) >= 0)
384 if (cf_parse_u64(optarg, &size))
397 fputs("Usage: sort-test [-v] [-s <size>] [-t <test>]\n", stderr);
406 for (uns i=0; i<TMAX; i++)