Commit | Line | Data |
---|---|---|
fec0f21c JA |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | ||
5 | #include "../fio.h" | |
6 | #include "../gettime.h" | |
9e52966e | 7 | #include "../fio_time.h" |
fec0f21c JA |
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" | |
82e3f7c4 | 19 | #include "../crc/sha3.h" |
844ea602 | 20 | #include "../crc/xxhash.h" |
f83ffd02 | 21 | #include "../crc/murmur3.h" |
951984d8 | 22 | #include "../crc/fnv.h" |
140dda40 | 23 | #include "../hash.h" |
fec0f21c | 24 | |
ea1f1da3 JA |
25 | #include "test.h" |
26 | ||
f7540869 JA |
27 | #define CHUNK 131072U |
28 | #define NR_CHUNKS 2048U | |
fec0f21c JA |
29 | |
30 | struct test_type { | |
31 | const char *name; | |
32 | unsigned int mask; | |
140dda40 JA |
33 | void (*fn)(struct test_type *, void *, size_t); |
34 | uint32_t output; | |
fec0f21c JA |
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, | |
844ea602 | 47 | T_XXHASH = 1U << 9, |
9f0e365d | 48 | T_MURMUR3 = 1U << 10, |
140dda40 | 49 | T_JHASH = 1U << 11, |
951984d8 | 50 | T_FNV = 1U << 12, |
82e3f7c4 JA |
51 | T_SHA3_224 = 1U << 13, |
52 | T_SHA3_256 = 1U << 14, | |
53 | T_SHA3_384 = 1U << 15, | |
54 | T_SHA3_512 = 1U << 16, | |
fec0f21c JA |
55 | }; |
56 | ||
140dda40 | 57 | static void t_md5(struct test_type *t, void *buf, size_t size) |
fec0f21c JA |
58 | { |
59 | uint32_t digest[4]; | |
60 | struct fio_md5_ctx ctx = { .hash = digest }; | |
fec0f21c JA |
61 | int i; |
62 | ||
63 | fio_md5_init(&ctx); | |
64 | ||
9c8566f5 | 65 | for (i = 0; i < NR_CHUNKS; i++) { |
24ef7a61 | 66 | fio_md5_update(&ctx, buf, size); |
9c8566f5 JA |
67 | fio_md5_final(&ctx); |
68 | } | |
fec0f21c JA |
69 | } |
70 | ||
140dda40 | 71 | static void t_crc64(struct test_type *t, void *buf, size_t size) |
fec0f21c | 72 | { |
fec0f21c JA |
73 | int i; |
74 | ||
fec0f21c | 75 | for (i = 0; i < NR_CHUNKS; i++) |
674c8f2f | 76 | t->output += fio_crc64(buf, size); |
fec0f21c JA |
77 | } |
78 | ||
140dda40 | 79 | static void t_crc32(struct test_type *t, void *buf, size_t size) |
fec0f21c | 80 | { |
fec0f21c JA |
81 | int i; |
82 | ||
fec0f21c | 83 | for (i = 0; i < NR_CHUNKS; i++) |
674c8f2f | 84 | t->output += fio_crc32(buf, size); |
fec0f21c JA |
85 | } |
86 | ||
140dda40 | 87 | static void t_crc32c(struct test_type *t, void *buf, size_t size) |
fec0f21c | 88 | { |
fec0f21c JA |
89 | int i; |
90 | ||
fec0f21c | 91 | for (i = 0; i < NR_CHUNKS; i++) |
674c8f2f | 92 | t->output += fio_crc32c(buf, size); |
fec0f21c JA |
93 | } |
94 | ||
140dda40 | 95 | static void t_crc16(struct test_type *t, void *buf, size_t size) |
fec0f21c | 96 | { |
fec0f21c JA |
97 | int i; |
98 | ||
fec0f21c | 99 | for (i = 0; i < NR_CHUNKS; i++) |
674c8f2f | 100 | t->output += fio_crc16(buf, size); |
fec0f21c JA |
101 | } |
102 | ||
140dda40 | 103 | static void t_crc7(struct test_type *t, void *buf, size_t size) |
fec0f21c | 104 | { |
fec0f21c JA |
105 | int i; |
106 | ||
fec0f21c | 107 | for (i = 0; i < NR_CHUNKS; i++) |
674c8f2f | 108 | t->output += fio_crc7(buf, size); |
fec0f21c JA |
109 | } |
110 | ||
140dda40 | 111 | static void t_sha1(struct test_type *t, void *buf, size_t size) |
fec0f21c JA |
112 | { |
113 | uint32_t sha[5]; | |
114 | struct fio_sha1_ctx ctx = { .H = sha }; | |
fec0f21c JA |
115 | int i; |
116 | ||
117 | fio_sha1_init(&ctx); | |
118 | ||
cbe00046 | 119 | for (i = 0; i < NR_CHUNKS; i++) { |
24ef7a61 | 120 | fio_sha1_update(&ctx, buf, size); |
cbe00046 JA |
121 | fio_sha1_final(&ctx); |
122 | } | |
fec0f21c JA |
123 | } |
124 | ||
140dda40 | 125 | static void t_sha256(struct test_type *t, void *buf, size_t size) |
fec0f21c JA |
126 | { |
127 | uint8_t sha[64]; | |
128 | struct fio_sha256_ctx ctx = { .buf = sha }; | |
fec0f21c JA |
129 | int i; |
130 | ||
131 | fio_sha256_init(&ctx); | |
132 | ||
9c8566f5 | 133 | for (i = 0; i < NR_CHUNKS; i++) { |
24ef7a61 | 134 | fio_sha256_update(&ctx, buf, size); |
9c8566f5 JA |
135 | fio_sha256_final(&ctx); |
136 | } | |
fec0f21c JA |
137 | } |
138 | ||
140dda40 | 139 | static void t_sha512(struct test_type *t, void *buf, size_t size) |
fec0f21c JA |
140 | { |
141 | uint8_t sha[128]; | |
142 | struct fio_sha512_ctx ctx = { .buf = sha }; | |
fec0f21c JA |
143 | int i; |
144 | ||
145 | fio_sha512_init(&ctx); | |
146 | ||
fec0f21c | 147 | for (i = 0; i < NR_CHUNKS; i++) |
24ef7a61 | 148 | fio_sha512_update(&ctx, buf, size); |
fec0f21c JA |
149 | } |
150 | ||
82e3f7c4 JA |
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 | ||
140dda40 | 207 | static void t_murmur3(struct test_type *t, void *buf, size_t size) |
9f0e365d JA |
208 | { |
209 | int i; | |
210 | ||
211 | for (i = 0; i < NR_CHUNKS; i++) | |
674c8f2f | 212 | t->output += murmurhash3(buf, size, 0x8989); |
9f0e365d JA |
213 | } |
214 | ||
140dda40 JA |
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 | ||
951984d8 JA |
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 | ||
140dda40 | 231 | static void t_xxhash(struct test_type *t, void *buf, size_t size) |
844ea602 JA |
232 | { |
233 | void *state; | |
844ea602 JA |
234 | int i; |
235 | ||
236 | state = XXH32_init(0x8989); | |
237 | ||
844ea602 | 238 | for (i = 0; i < NR_CHUNKS; i++) |
24ef7a61 | 239 | XXH32_update(state, buf, size); |
844ea602 | 240 | |
140dda40 | 241 | t->output = XXH32_digest(state); |
844ea602 JA |
242 | } |
243 | ||
fec0f21c JA |
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 | }, | |
844ea602 JA |
290 | { |
291 | .name = "xxhash", | |
292 | .mask = T_XXHASH, | |
293 | .fn = t_xxhash, | |
294 | }, | |
9f0e365d JA |
295 | { |
296 | .name = "murmur3", | |
297 | .mask = T_MURMUR3, | |
298 | .fn = t_murmur3, | |
299 | }, | |
140dda40 JA |
300 | { |
301 | .name = "jhash", | |
302 | .mask = T_JHASH, | |
303 | .fn = t_jhash, | |
304 | }, | |
951984d8 JA |
305 | { |
306 | .name = "fnv", | |
307 | .mask = T_FNV, | |
308 | .fn = t_fnv, | |
309 | }, | |
82e3f7c4 JA |
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 | }, | |
fec0f21c JA |
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++) { | |
f7540869 | 346 | if (!strcmp(t[i].name, name)) { |
fec0f21c JA |
347 | mask |= t[i].mask; |
348 | break; | |
349 | } | |
350 | } | |
351 | } | |
352 | ||
353 | free(ostr); | |
354 | return mask; | |
355 | } | |
356 | ||
782744ef JA |
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 | ||
24ef7a61 | 364 | return 1; |
782744ef JA |
365 | } |
366 | ||
fec0f21c JA |
367 | int fio_crctest(const char *type) |
368 | { | |
369 | unsigned int test_mask = 0; | |
370 | uint64_t mb = CHUNK * NR_CHUNKS; | |
ae7e055f | 371 | struct frand_state state; |
24ef7a61 JA |
372 | int i, first = 1; |
373 | void *buf; | |
fec0f21c | 374 | |
214e2d56 | 375 | crc32c_arm64_probe(); |
fec0f21c JA |
376 | crc32c_intel_probe(); |
377 | ||
378 | if (!type) | |
379 | test_mask = ~0U; | |
782744ef JA |
380 | else if (!strcmp(type, "help") || !strcmp(type, "list")) |
381 | return list_types(); | |
fec0f21c JA |
382 | else |
383 | test_mask = get_test_mask(type); | |
384 | ||
24ef7a61 JA |
385 | if (!test_mask) { |
386 | fprintf(stderr, "fio: unknown hash `%s`. Available:\n", type); | |
387 | return list_types(); | |
388 | } | |
389 | ||
390 | buf = malloc(CHUNK); | |
c3546b53 | 391 | init_rand_seed(&state, 0x8989, 0); |
ae7e055f | 392 | fill_random_buf(&state, buf, CHUNK); |
24ef7a61 | 393 | |
fec0f21c | 394 | for (i = 0; t[i].name; i++) { |
ae7e055f | 395 | struct timeval tv; |
fec0f21c JA |
396 | double mb_sec; |
397 | uint64_t usec; | |
d78bbd4c | 398 | char pre[3]; |
fec0f21c JA |
399 | |
400 | if (!(t[i].mask & test_mask)) | |
401 | continue; | |
402 | ||
ae7e055f JA |
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); | |
140dda40 | 409 | t[i].fn(&t[i], buf, CHUNK); |
ae7e055f JA |
410 | } |
411 | ||
412 | fio_gettime(&tv, NULL); | |
140dda40 | 413 | t[i].fn(&t[i], buf, CHUNK); |
ae7e055f | 414 | usec = utime_since_now(&tv); |
24ef7a61 | 415 | |
e5607fe5 JA |
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"); | |
4870138d | 423 | printf("%s:%s%8.2f MiB/sec\n", t[i].name, pre, mb_sec); |
e5607fe5 | 424 | } else |
4870138d | 425 | printf("%s:inf MiB/sec\n", t[i].name); |
24ef7a61 | 426 | first = 0; |
fec0f21c | 427 | } |
782744ef | 428 | |
24ef7a61 | 429 | free(buf); |
fec0f21c JA |
430 | return 0; |
431 | } |