• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
t_md5(struct test_type * t,void * buf,size_t size)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 
t_crc64(struct test_type * t,void * buf,size_t size)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 
t_crc32(struct test_type * t,void * buf,size_t size)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 
t_crc32c(struct test_type * t,void * buf,size_t size)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 
t_crc16(struct test_type * t,void * buf,size_t size)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 
t_crc7(struct test_type * t,void * buf,size_t size)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 
t_sha1(struct test_type * t,void * buf,size_t size)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 
t_sha256(struct test_type * t,void * buf,size_t size)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 
t_sha512(struct test_type * t,void * buf,size_t size)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 
t_sha3_224(struct test_type * t,void * buf,size_t size)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 
t_sha3_256(struct test_type * t,void * buf,size_t size)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 
t_sha3_384(struct test_type * t,void * buf,size_t size)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 
t_sha3_512(struct test_type * t,void * buf,size_t size)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 
t_murmur3(struct test_type * t,void * buf,size_t size)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 
t_jhash(struct test_type * t,void * buf,size_t size)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 
t_fnv(struct test_type * t,void * buf,size_t size)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 
t_xxhash(struct test_type * t,void * buf,size_t size)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 
get_test_mask(const char * type)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 
list_types(void)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 
fio_crctest(const char * type)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 timeval tv;
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(&tv, NULL);
413 		t[i].fn(&t[i], buf, CHUNK);
414 		usec = utime_since_now(&tv);
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 }
432