174bea375136f01cefe1aa60e560bce04de875ae
[fio.git] / crc / test.c
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
24 struct test_type {
25         const char *name;
26         unsigned int mask;
27         uint64_t (*fn)(void);
28 };
29
30 enum {
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
43 static 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
51 static 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
74 static 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
93 static 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
112 static 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
131 static 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
150 static 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
169 static 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
192 static 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
215 static 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
238 static 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
261 static 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
317 static 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
339 static 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
349 int 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 }