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