2f6d9ee7f430c1a05a5d00c328b8a35e33e6fc2d
[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
20 #define CHUNK           131072U
21 #define NR_CHUNKS         2048U
22
23 struct test_type {
24         const char *name;
25         unsigned int mask;
26         uint64_t (*fn)(void);
27 };
28
29 enum {
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
41 static 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
49 static 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
72 static 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
91 static 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
110 static 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
129 static 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
148 static 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
167 static 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
190 static 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
213 static 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
236 static 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
287 static 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 (!strcmp(t[i].name, name)) {
299                                 mask |= t[i].mask;
300                                 break;
301                         }
302                 }
303         }
304
305         free(ostr);
306         return mask;
307 }
308
309 static int list_types(void)
310 {
311         int i;
312
313         for (i = 0; t[i].name; i++)
314                 printf("%s\n", t[i].name);
315
316         return 0;
317 }
318
319 int fio_crctest(const char *type)
320 {
321         unsigned int test_mask = 0;
322         uint64_t mb = CHUNK * NR_CHUNKS;
323         int i;
324
325         crc32c_intel_probe();
326
327         if (!type)
328                 test_mask = ~0U;
329         else if (!strcmp(type, "help") || !strcmp(type, "list"))
330                 return list_types();
331         else
332                 test_mask = get_test_mask(type);
333
334         for (i = 0; t[i].name; i++) {
335                 double mb_sec;
336                 uint64_t usec;
337
338                 if (!(t[i].mask & test_mask))
339                         continue;
340
341                 usec = t[i].fn();
342                 mb_sec = (double) mb / (double) usec;
343                 mb_sec /= (1.024 * 1.024);
344                 printf("%s:\t%.2f MB/sec\n", t[i].name, mb_sec);
345         }
346
347         return 0;
348 }