• 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 
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 	uint64_t (*fn)(void);
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 
randomize_buf(void * buf,unsigned int size,int seed)45 static void randomize_buf(void *buf, unsigned int size, int seed)
46 {
47 	struct frand_state state;
48 
49 	init_rand_seed(&state, seed);
50 	fill_random_buf(&state, buf, size);
51 }
52 
t_md5(void)53 static uint64_t t_md5(void)
54 {
55 	uint32_t digest[4];
56 	struct fio_md5_ctx ctx = { .hash = digest };
57 	struct timeval s;
58 	uint64_t ret;
59 	void *buf;
60 	int i;
61 
62 	fio_md5_init(&ctx);
63 
64 	buf = malloc(CHUNK);
65 	randomize_buf(buf, CHUNK, 0x8989);
66 
67 	fio_gettime(&s, NULL);
68 	for (i = 0; i < NR_CHUNKS; i++)
69 		fio_md5_update(&ctx, buf, CHUNK);
70 
71 	ret = utime_since_now(&s);
72 	free(buf);
73 	return ret;
74 }
75 
t_crc64(void)76 static uint64_t t_crc64(void)
77 {
78 	struct timeval s;
79 	uint64_t ret;
80 	void *buf;
81 	int i;
82 
83 	buf = malloc(CHUNK);
84 	randomize_buf(buf, CHUNK, 0x8989);
85 
86 	fio_gettime(&s, NULL);
87 	for (i = 0; i < NR_CHUNKS; i++)
88 		fio_crc64(buf, CHUNK);
89 
90 	ret = utime_since_now(&s);
91 	free(buf);
92 	return ret;
93 }
94 
t_crc32(void)95 static uint64_t t_crc32(void)
96 {
97 	struct timeval s;
98 	uint64_t ret;
99 	void *buf;
100 	int i;
101 
102 	buf = malloc(CHUNK);
103 	randomize_buf(buf, CHUNK, 0x8989);
104 
105 	fio_gettime(&s, NULL);
106 	for (i = 0; i < NR_CHUNKS; i++)
107 		fio_crc32(buf, CHUNK);
108 
109 	ret = utime_since_now(&s);
110 	free(buf);
111 	return ret;
112 }
113 
t_crc32c(void)114 static uint64_t t_crc32c(void)
115 {
116 	struct timeval s;
117 	uint64_t ret;
118 	void *buf;
119 	int i;
120 
121 	buf = malloc(CHUNK);
122 	randomize_buf(buf, CHUNK, 0x8989);
123 
124 	fio_gettime(&s, NULL);
125 	for (i = 0; i < NR_CHUNKS; i++)
126 		fio_crc32c(buf, CHUNK);
127 
128 	ret = utime_since_now(&s);
129 	free(buf);
130 	return ret;
131 }
132 
t_crc16(void)133 static uint64_t t_crc16(void)
134 {
135 	struct timeval s;
136 	uint64_t ret;
137 	void *buf;
138 	int i;
139 
140 	buf = malloc(CHUNK);
141 	randomize_buf(buf, CHUNK, 0x8989);
142 
143 	fio_gettime(&s, NULL);
144 	for (i = 0; i < NR_CHUNKS; i++)
145 		fio_crc16(buf, CHUNK);
146 
147 	ret = utime_since_now(&s);
148 	free(buf);
149 	return ret;
150 }
151 
t_crc7(void)152 static uint64_t t_crc7(void)
153 {
154 	struct timeval s;
155 	uint64_t ret;
156 	void *buf;
157 	int i;
158 
159 	buf = malloc(CHUNK);
160 	randomize_buf(buf, CHUNK, 0x8989);
161 
162 	fio_gettime(&s, NULL);
163 	for (i = 0; i < NR_CHUNKS; i++)
164 		fio_crc7(buf, CHUNK);
165 
166 	ret = utime_since_now(&s);
167 	free(buf);
168 	return ret;
169 }
170 
t_sha1(void)171 static uint64_t t_sha1(void)
172 {
173 	uint32_t sha[5];
174 	struct fio_sha1_ctx ctx = { .H = sha };
175 	struct timeval s;
176 	uint64_t ret;
177 	void *buf;
178 	int i;
179 
180 	fio_sha1_init(&ctx);
181 
182 	buf = malloc(CHUNK);
183 	randomize_buf(buf, CHUNK, 0x8989);
184 
185 	fio_gettime(&s, NULL);
186 	for (i = 0; i < NR_CHUNKS; i++)
187 		fio_sha1_update(&ctx, buf, CHUNK);
188 
189 	ret = utime_since_now(&s);
190 	free(buf);
191 	return ret;
192 }
193 
t_sha256(void)194 static uint64_t t_sha256(void)
195 {
196 	uint8_t sha[64];
197 	struct fio_sha256_ctx ctx = { .buf = sha };
198 	struct timeval s;
199 	uint64_t ret;
200 	void *buf;
201 	int i;
202 
203 	fio_sha256_init(&ctx);
204 
205 	buf = malloc(CHUNK);
206 	randomize_buf(buf, CHUNK, 0x8989);
207 
208 	fio_gettime(&s, NULL);
209 	for (i = 0; i < NR_CHUNKS; i++)
210 		fio_sha256_update(&ctx, buf, CHUNK);
211 
212 	ret = utime_since_now(&s);
213 	free(buf);
214 	return ret;
215 }
216 
t_sha512(void)217 static uint64_t t_sha512(void)
218 {
219 	uint8_t sha[128];
220 	struct fio_sha512_ctx ctx = { .buf = sha };
221 	struct timeval s;
222 	uint64_t ret;
223 	void *buf;
224 	int i;
225 
226 	fio_sha512_init(&ctx);
227 
228 	buf = malloc(CHUNK);
229 	randomize_buf(buf, CHUNK, 0x8989);
230 
231 	fio_gettime(&s, NULL);
232 	for (i = 0; i < NR_CHUNKS; i++)
233 		fio_sha512_update(&ctx, buf, CHUNK);
234 
235 	ret = utime_since_now(&s);
236 	free(buf);
237 	return ret;
238 }
239 
t_xxhash(void)240 static uint64_t t_xxhash(void)
241 {
242 	void *state;
243 	struct timeval s;
244 	uint64_t ret;
245 	void *buf;
246 	int i;
247 
248 	state = XXH32_init(0x8989);
249 
250 	buf = malloc(CHUNK);
251 	randomize_buf(buf, CHUNK, 0x8989);
252 
253 	fio_gettime(&s, NULL);
254 	for (i = 0; i < NR_CHUNKS; i++)
255 		XXH32_update(state, buf, CHUNK);
256 
257 	XXH32_digest(state);
258 	ret = utime_since_now(&s);
259 	free(buf);
260 	return ret;
261 }
262 
263 static struct test_type t[] = {
264 	{
265 		.name = "md5",
266 		.mask = T_MD5,
267 		.fn = t_md5,
268 	},
269 	{
270 		.name = "crc64",
271 		.mask = T_CRC64,
272 		.fn = t_crc64,
273 	},
274 	{
275 		.name = "crc32",
276 		.mask = T_CRC32,
277 		.fn = t_crc32,
278 	},
279 	{
280 		.name = "crc32c",
281 		.mask = T_CRC32C,
282 		.fn = t_crc32c,
283 	},
284 	{
285 		.name = "crc16",
286 		.mask = T_CRC16,
287 		.fn = t_crc16,
288 	},
289 	{
290 		.name = "crc7",
291 		.mask = T_CRC7,
292 		.fn = t_crc7,
293 	},
294 	{
295 		.name = "sha1",
296 		.mask = T_SHA1,
297 		.fn = t_sha1,
298 	},
299 	{
300 		.name = "sha256",
301 		.mask = T_SHA256,
302 		.fn = t_sha256,
303 	},
304 	{
305 		.name = "sha512",
306 		.mask = T_SHA512,
307 		.fn = t_sha512,
308 	},
309 	{
310 		.name = "xxhash",
311 		.mask = T_XXHASH,
312 		.fn = t_xxhash,
313 	},
314 	{
315 		.name = NULL,
316 	},
317 };
318 
get_test_mask(const char * type)319 static unsigned int get_test_mask(const char *type)
320 {
321 	char *ostr, *str = strdup(type);
322 	unsigned int mask;
323 	char *name;
324 	int i;
325 
326 	ostr = str;
327 	mask = 0;
328 	while ((name = strsep(&str, ",")) != NULL) {
329 		for (i = 0; t[i].name; i++) {
330 			if (!strcmp(t[i].name, name)) {
331 				mask |= t[i].mask;
332 				break;
333 			}
334 		}
335 	}
336 
337 	free(ostr);
338 	return mask;
339 }
340 
list_types(void)341 static int list_types(void)
342 {
343 	int i;
344 
345 	for (i = 0; t[i].name; i++)
346 		printf("%s\n", t[i].name);
347 
348 	return 0;
349 }
350 
fio_crctest(const char * type)351 int fio_crctest(const char *type)
352 {
353 	unsigned int test_mask = 0;
354 	uint64_t mb = CHUNK * NR_CHUNKS;
355 	int i;
356 
357 	crc32c_intel_probe();
358 
359 	if (!type)
360 		test_mask = ~0U;
361 	else if (!strcmp(type, "help") || !strcmp(type, "list"))
362 		return list_types();
363 	else
364 		test_mask = get_test_mask(type);
365 
366 	for (i = 0; t[i].name; i++) {
367 		double mb_sec;
368 		uint64_t usec;
369 
370 		if (!(t[i].mask & test_mask))
371 			continue;
372 
373 		usec = t[i].fn();
374 		mb_sec = (double) mb / (double) usec;
375 		mb_sec /= (1.024 * 1.024);
376 		printf("%s:\t%.2f MB/sec\n", t[i].name, mb_sec);
377 	}
378 
379 	return 0;
380 }
381