Fix min/max typeof warnings
[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/xxhash.h"
20
21 #include "test.h"
22
23 #define CHUNK           131072U
24 #define NR_CHUNKS         2048U
25
26 struct test_type {
27         const char *name;
28         unsigned int mask;
29         void (*fn)(void *, size_t);
30 };
31
32 enum {
33         T_MD5           = 1U << 0,
34         T_CRC64         = 1U << 1,
35         T_CRC32         = 1U << 2,
36         T_CRC32C        = 1U << 3,
37         T_CRC16         = 1U << 4,
38         T_CRC7          = 1U << 5,
39         T_SHA1          = 1U << 6,
40         T_SHA256        = 1U << 7,
41         T_SHA512        = 1U << 8,
42         T_XXHASH        = 1U << 9,
43 };
44
45 static void t_md5(void *buf, size_t size)
46 {
47         uint32_t digest[4];
48         struct fio_md5_ctx ctx = { .hash = digest };
49         int i;
50
51         fio_md5_init(&ctx);
52
53         for (i = 0; i < NR_CHUNKS; i++)
54                 fio_md5_update(&ctx, buf, size);
55 }
56
57 static void t_crc64(void *buf, size_t size)
58 {
59         int i;
60
61         for (i = 0; i < NR_CHUNKS; i++)
62                 fio_crc64(buf, size);
63 }
64
65 static void t_crc32(void *buf, size_t size)
66 {
67         int i;
68
69         for (i = 0; i < NR_CHUNKS; i++)
70                 fio_crc32(buf, size);
71 }
72
73 static void t_crc32c(void *buf, size_t size)
74 {
75         int i;
76
77         for (i = 0; i < NR_CHUNKS; i++)
78                 fio_crc32c(buf, size);
79 }
80
81 static void t_crc16(void *buf, size_t size)
82 {
83         int i;
84
85         for (i = 0; i < NR_CHUNKS; i++)
86                 fio_crc16(buf, size);
87 }
88
89 static void t_crc7(void *buf, size_t size)
90 {
91         int i;
92
93         for (i = 0; i < NR_CHUNKS; i++)
94                 fio_crc7(buf, size);
95 }
96
97 static void t_sha1(void *buf, size_t size)
98 {
99         uint32_t sha[5];
100         struct fio_sha1_ctx ctx = { .H = sha };
101         int i;
102
103         fio_sha1_init(&ctx);
104
105         for (i = 0; i < NR_CHUNKS; i++)
106                 fio_sha1_update(&ctx, buf, size);
107 }
108
109 static void t_sha256(void *buf, size_t size)
110 {
111         uint8_t sha[64];
112         struct fio_sha256_ctx ctx = { .buf = sha };
113         int i;
114
115         fio_sha256_init(&ctx);
116
117         for (i = 0; i < NR_CHUNKS; i++)
118                 fio_sha256_update(&ctx, buf, size);
119 }
120
121 static void t_sha512(void *buf, size_t size)
122 {
123         uint8_t sha[128];
124         struct fio_sha512_ctx ctx = { .buf = sha };
125         int i;
126
127         fio_sha512_init(&ctx);
128
129         for (i = 0; i < NR_CHUNKS; i++)
130                 fio_sha512_update(&ctx, buf, size);
131 }
132
133 static void t_xxhash(void *buf, size_t size)
134 {
135         void *state;
136         int i;
137
138         state = XXH32_init(0x8989);
139
140         for (i = 0; i < NR_CHUNKS; i++)
141                 XXH32_update(state, buf, size);
142
143         XXH32_digest(state);
144 }
145
146 static struct test_type t[] = {
147         {
148                 .name = "md5",
149                 .mask = T_MD5,
150                 .fn = t_md5,
151         },
152         {
153                 .name = "crc64",
154                 .mask = T_CRC64,
155                 .fn = t_crc64,
156         },
157         {
158                 .name = "crc32",
159                 .mask = T_CRC32,
160                 .fn = t_crc32,
161         },
162         {
163                 .name = "crc32c",
164                 .mask = T_CRC32C,
165                 .fn = t_crc32c,
166         },
167         {
168                 .name = "crc16",
169                 .mask = T_CRC16,
170                 .fn = t_crc16,
171         },
172         {
173                 .name = "crc7",
174                 .mask = T_CRC7,
175                 .fn = t_crc7,
176         },
177         {
178                 .name = "sha1",
179                 .mask = T_SHA1,
180                 .fn = t_sha1,
181         },
182         {
183                 .name = "sha256",
184                 .mask = T_SHA256,
185                 .fn = t_sha256,
186         },
187         {
188                 .name = "sha512",
189                 .mask = T_SHA512,
190                 .fn = t_sha512,
191         },
192         {
193                 .name = "xxhash",
194                 .mask = T_XXHASH,
195                 .fn = t_xxhash,
196         },
197         {
198                 .name = NULL,
199         },
200 };
201
202 static unsigned int get_test_mask(const char *type)
203 {
204         char *ostr, *str = strdup(type);
205         unsigned int mask;
206         char *name;
207         int i;
208
209         ostr = str;
210         mask = 0;
211         while ((name = strsep(&str, ",")) != NULL) {
212                 for (i = 0; t[i].name; i++) {
213                         if (!strcmp(t[i].name, name)) {
214                                 mask |= t[i].mask;
215                                 break;
216                         }
217                 }
218         }
219
220         free(ostr);
221         return mask;
222 }
223
224 static int list_types(void)
225 {
226         int i;
227
228         for (i = 0; t[i].name; i++)
229                 printf("%s\n", t[i].name);
230
231         return 1;
232 }
233
234 int fio_crctest(const char *type)
235 {
236         unsigned int test_mask = 0;
237         uint64_t mb = CHUNK * NR_CHUNKS;
238         struct frand_state state;
239         int i, first = 1;
240         void *buf;
241
242         crc32c_intel_probe();
243
244         if (!type)
245                 test_mask = ~0U;
246         else if (!strcmp(type, "help") || !strcmp(type, "list"))
247                 return list_types();
248         else
249                 test_mask = get_test_mask(type);
250
251         if (!test_mask) {
252                 fprintf(stderr, "fio: unknown hash `%s`. Available:\n", type);
253                 return list_types();
254         }
255
256         buf = malloc(CHUNK);
257         init_rand_seed(&state, 0x8989);
258         fill_random_buf(&state, buf, CHUNK);
259
260         for (i = 0; t[i].name; i++) {
261                 struct timeval tv;
262                 double mb_sec;
263                 uint64_t usec;
264
265                 if (!(t[i].mask & test_mask))
266                         continue;
267
268                 /*
269                  * For first run, make sure CPUs are spun up and that
270                  * we've touched the data.
271                  */
272                 if (first) {
273                         usec_spin(100000);
274                         t[i].fn(buf, CHUNK);
275                 }
276
277                 fio_gettime(&tv, NULL);
278                 t[i].fn(buf, CHUNK);
279                 usec = utime_since_now(&tv);
280
281                 mb_sec = (double) mb / (double) usec;
282                 mb_sec /= (1.024 * 1.024);
283                 printf("%s:\t%8.2f MB/sec\n", t[i].name, mb_sec);
284                 first = 0;
285         }
286
287         free(buf);
288         return 0;
289 }