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