nanosecond: initial commit changing timeval to timespec
[fio.git] / crc / test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "../fio.h"
6 #include "../gettime.h"
7 #include "../fio_time.h"
8 #include "../verify.h"
9
10 #include "../crc/md5.h"
11 #include "../crc/crc64.h"
12 #include "../crc/crc32.h"
13 #include "../crc/crc32c.h"
14 #include "../crc/crc16.h"
15 #include "../crc/crc7.h"
16 #include "../crc/sha1.h"
17 #include "../crc/sha256.h"
18 #include "../crc/sha512.h"
19 #include "../crc/sha3.h"
20 #include "../crc/xxhash.h"
21 #include "../crc/murmur3.h"
22 #include "../crc/fnv.h"
23 #include "../hash.h"
24
25 #include "test.h"
26
27 #define CHUNK           131072U
28 #define NR_CHUNKS         2048U
29
30 struct test_type {
31         const char *name;
32         unsigned int mask;
33         void (*fn)(struct test_type *, void *, size_t);
34         uint32_t output;
35 };
36
37 enum {
38         T_MD5           = 1U << 0,
39         T_CRC64         = 1U << 1,
40         T_CRC32         = 1U << 2,
41         T_CRC32C        = 1U << 3,
42         T_CRC16         = 1U << 4,
43         T_CRC7          = 1U << 5,
44         T_SHA1          = 1U << 6,
45         T_SHA256        = 1U << 7,
46         T_SHA512        = 1U << 8,
47         T_XXHASH        = 1U << 9,
48         T_MURMUR3       = 1U << 10,
49         T_JHASH         = 1U << 11,
50         T_FNV           = 1U << 12,
51         T_SHA3_224      = 1U << 13,
52         T_SHA3_256      = 1U << 14,
53         T_SHA3_384      = 1U << 15,
54         T_SHA3_512      = 1U << 16,
55 };
56
57 static void t_md5(struct test_type *t, void *buf, size_t size)
58 {
59         uint32_t digest[4];
60         struct fio_md5_ctx ctx = { .hash = digest };
61         int i;
62
63         fio_md5_init(&ctx);
64
65         for (i = 0; i < NR_CHUNKS; i++) {
66                 fio_md5_update(&ctx, buf, size);
67                 fio_md5_final(&ctx);
68         }
69 }
70
71 static void t_crc64(struct test_type *t, void *buf, size_t size)
72 {
73         int i;
74
75         for (i = 0; i < NR_CHUNKS; i++)
76                 t->output += fio_crc64(buf, size);
77 }
78
79 static void t_crc32(struct test_type *t, void *buf, size_t size)
80 {
81         int i;
82
83         for (i = 0; i < NR_CHUNKS; i++)
84                 t->output += fio_crc32(buf, size);
85 }
86
87 static void t_crc32c(struct test_type *t, void *buf, size_t size)
88 {
89         int i;
90
91         for (i = 0; i < NR_CHUNKS; i++)
92                 t->output += fio_crc32c(buf, size);
93 }
94
95 static void t_crc16(struct test_type *t, void *buf, size_t size)
96 {
97         int i;
98
99         for (i = 0; i < NR_CHUNKS; i++)
100                 t->output += fio_crc16(buf, size);
101 }
102
103 static void t_crc7(struct test_type *t, void *buf, size_t size)
104 {
105         int i;
106
107         for (i = 0; i < NR_CHUNKS; i++)
108                 t->output += fio_crc7(buf, size);
109 }
110
111 static void t_sha1(struct test_type *t, void *buf, size_t size)
112 {
113         uint32_t sha[5];
114         struct fio_sha1_ctx ctx = { .H = sha };
115         int i;
116
117         fio_sha1_init(&ctx);
118
119         for (i = 0; i < NR_CHUNKS; i++) {
120                 fio_sha1_update(&ctx, buf, size);
121                 fio_sha1_final(&ctx);
122         }
123 }
124
125 static void t_sha256(struct test_type *t, void *buf, size_t size)
126 {
127         uint8_t sha[64];
128         struct fio_sha256_ctx ctx = { .buf = sha };
129         int i;
130
131         fio_sha256_init(&ctx);
132
133         for (i = 0; i < NR_CHUNKS; i++) {
134                 fio_sha256_update(&ctx, buf, size);
135                 fio_sha256_final(&ctx);
136         }
137 }
138
139 static void t_sha512(struct test_type *t, void *buf, size_t size)
140 {
141         uint8_t sha[128];
142         struct fio_sha512_ctx ctx = { .buf = sha };
143         int i;
144
145         fio_sha512_init(&ctx);
146
147         for (i = 0; i < NR_CHUNKS; i++)
148                 fio_sha512_update(&ctx, buf, size);
149 }
150
151 static void t_sha3_224(struct test_type *t, void *buf, size_t size)
152 {
153         uint8_t sha[SHA3_224_DIGEST_SIZE];
154         struct fio_sha3_ctx ctx = { .sha = sha };
155         int i;
156
157         fio_sha3_224_init(&ctx);
158
159         for (i = 0; i < NR_CHUNKS; i++) {
160                 fio_sha3_update(&ctx, buf, size);
161                 fio_sha3_final(&ctx);
162         }
163 }
164
165 static void t_sha3_256(struct test_type *t, void *buf, size_t size)
166 {
167         uint8_t sha[SHA3_256_DIGEST_SIZE];
168         struct fio_sha3_ctx ctx = { .sha = sha };
169         int i;
170
171         fio_sha3_256_init(&ctx);
172
173         for (i = 0; i < NR_CHUNKS; i++) {
174                 fio_sha3_update(&ctx, buf, size);
175                 fio_sha3_final(&ctx);
176         }
177 }
178
179 static void t_sha3_384(struct test_type *t, void *buf, size_t size)
180 {
181         uint8_t sha[SHA3_384_DIGEST_SIZE];
182         struct fio_sha3_ctx ctx = { .sha = sha };
183         int i;
184
185         fio_sha3_384_init(&ctx);
186
187         for (i = 0; i < NR_CHUNKS; i++) {
188                 fio_sha3_update(&ctx, buf, size);
189                 fio_sha3_final(&ctx);
190         }
191 }
192
193 static void t_sha3_512(struct test_type *t, void *buf, size_t size)
194 {
195         uint8_t sha[SHA3_512_DIGEST_SIZE];
196         struct fio_sha3_ctx ctx = { .sha = sha };
197         int i;
198
199         fio_sha3_512_init(&ctx);
200
201         for (i = 0; i < NR_CHUNKS; i++) {
202                 fio_sha3_update(&ctx, buf, size);
203                 fio_sha3_final(&ctx);
204         }
205 }
206
207 static void t_murmur3(struct test_type *t, void *buf, size_t size)
208 {
209         int i;
210
211         for (i = 0; i < NR_CHUNKS; i++)
212                 t->output += murmurhash3(buf, size, 0x8989);
213 }
214
215 static void t_jhash(struct test_type *t, void *buf, size_t size)
216 {
217         int i;
218
219         for (i = 0; i < NR_CHUNKS; i++)
220                 t->output += jhash(buf, size, 0x8989);
221 }
222
223 static void t_fnv(struct test_type *t, void *buf, size_t size)
224 {
225         int i;
226
227         for (i = 0; i < NR_CHUNKS; i++)
228                 t->output += fnv(buf, size, 0x8989);
229 }
230
231 static void t_xxhash(struct test_type *t, void *buf, size_t size)
232 {
233         void *state;
234         int i;
235
236         state = XXH32_init(0x8989);
237
238         for (i = 0; i < NR_CHUNKS; i++)
239                 XXH32_update(state, buf, size);
240
241         t->output = XXH32_digest(state);
242 }
243
244 static struct test_type t[] = {
245         {
246                 .name = "md5",
247                 .mask = T_MD5,
248                 .fn = t_md5,
249         },
250         {
251                 .name = "crc64",
252                 .mask = T_CRC64,
253                 .fn = t_crc64,
254         },
255         {
256                 .name = "crc32",
257                 .mask = T_CRC32,
258                 .fn = t_crc32,
259         },
260         {
261                 .name = "crc32c",
262                 .mask = T_CRC32C,
263                 .fn = t_crc32c,
264         },
265         {
266                 .name = "crc16",
267                 .mask = T_CRC16,
268                 .fn = t_crc16,
269         },
270         {
271                 .name = "crc7",
272                 .mask = T_CRC7,
273                 .fn = t_crc7,
274         },
275         {
276                 .name = "sha1",
277                 .mask = T_SHA1,
278                 .fn = t_sha1,
279         },
280         {
281                 .name = "sha256",
282                 .mask = T_SHA256,
283                 .fn = t_sha256,
284         },
285         {
286                 .name = "sha512",
287                 .mask = T_SHA512,
288                 .fn = t_sha512,
289         },
290         {
291                 .name = "xxhash",
292                 .mask = T_XXHASH,
293                 .fn = t_xxhash,
294         },
295         {
296                 .name = "murmur3",
297                 .mask = T_MURMUR3,
298                 .fn = t_murmur3,
299         },
300         {
301                 .name = "jhash",
302                 .mask = T_JHASH,
303                 .fn = t_jhash,
304         },
305         {
306                 .name = "fnv",
307                 .mask = T_FNV,
308                 .fn = t_fnv,
309         },
310         {
311                 .name = "sha3-224",
312                 .mask = T_SHA3_224,
313                 .fn = t_sha3_224,
314         },
315         {
316                 .name = "sha3-256",
317                 .mask = T_SHA3_256,
318                 .fn = t_sha3_256,
319         },
320         {
321                 .name = "sha3-384",
322                 .mask = T_SHA3_384,
323                 .fn = t_sha3_384,
324         },
325         {
326                 .name = "sha3-512",
327                 .mask = T_SHA3_512,
328                 .fn = t_sha3_512,
329         },
330         {
331                 .name = NULL,
332         },
333 };
334
335 static unsigned int get_test_mask(const char *type)
336 {
337         char *ostr, *str = strdup(type);
338         unsigned int mask;
339         char *name;
340         int i;
341
342         ostr = str;
343         mask = 0;
344         while ((name = strsep(&str, ",")) != NULL) {
345                 for (i = 0; t[i].name; i++) {
346                         if (!strcmp(t[i].name, name)) {
347                                 mask |= t[i].mask;
348                                 break;
349                         }
350                 }
351         }
352
353         free(ostr);
354         return mask;
355 }
356
357 static int list_types(void)
358 {
359         int i;
360
361         for (i = 0; t[i].name; i++)
362                 printf("%s\n", t[i].name);
363
364         return 1;
365 }
366
367 int fio_crctest(const char *type)
368 {
369         unsigned int test_mask = 0;
370         uint64_t mb = CHUNK * NR_CHUNKS;
371         struct frand_state state;
372         int i, first = 1;
373         void *buf;
374
375         crc32c_arm64_probe();
376         crc32c_intel_probe();
377
378         if (!type)
379                 test_mask = ~0U;
380         else if (!strcmp(type, "help") || !strcmp(type, "list"))
381                 return list_types();
382         else
383                 test_mask = get_test_mask(type);
384
385         if (!test_mask) {
386                 fprintf(stderr, "fio: unknown hash `%s`. Available:\n", type);
387                 return list_types();
388         }
389
390         buf = malloc(CHUNK);
391         init_rand_seed(&state, 0x8989, 0);
392         fill_random_buf(&state, buf, CHUNK);
393
394         for (i = 0; t[i].name; i++) {
395                 struct timespec ts;
396                 double mb_sec;
397                 uint64_t usec;
398                 char pre[3];
399
400                 if (!(t[i].mask & test_mask))
401                         continue;
402
403                 /*
404                  * For first run, make sure CPUs are spun up and that
405                  * we've touched the data.
406                  */
407                 if (first) {
408                         usec_spin(100000);
409                         t[i].fn(&t[i], buf, CHUNK);
410                 }
411
412                 fio_gettime(&ts, NULL);
413                 t[i].fn(&t[i], buf, CHUNK);
414                 usec = utime_since_now(&ts);
415
416                 if (usec) {
417                         mb_sec = (double) mb / (double) usec;
418                         mb_sec /= (1.024 * 1.024);
419                         if (strlen(t[i].name) >= 7)
420                                 sprintf(pre, "\t");
421                         else
422                                 sprintf(pre, "\t\t");
423                         printf("%s:%s%8.2f MiB/sec\n", t[i].name, pre, mb_sec);
424                 } else
425                         printf("%s:inf MiB/sec\n", t[i].name);
426                 first = 0;
427         }
428
429         free(buf);
430         return 0;
431 }