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