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