3ce717a0d7751cde0879a7507ac0d75e05e3c464
[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 "../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
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
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
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
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
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
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
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
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
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
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
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
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
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
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%8.2f MB/sec\n", t[i].name, mb_sec);
377         }
378
379         return 0;
380 }