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