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