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