blob: dbc5653ffc14410711ed6a7df1a7d333aae0a629 [file] [log] [blame]
Jens Axboefec0f212014-02-07 14:39:33 -07001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "../fio.h"
6#include "../gettime.h"
Danny Al-Gaaf9e529662014-04-30 20:48:16 +02007#include "../fio_time.h"
Jens Axboefec0f212014-02-07 14:39:33 -07008#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"
Jens Axboe844ea602014-02-20 13:21:45 -080019#include "../crc/xxhash.h"
Jens Axboeb0e1bb92014-09-27 09:30:56 -060020#include "../crc/murmur3.h"
Jens Axboe262cf5c2014-09-27 21:27:48 -060021#include "../crc/fnv.h"
Jens Axboe95a5a3f2014-09-27 09:29:42 -060022#include "../hash.h"
Jens Axboefec0f212014-02-07 14:39:33 -070023
Jens Axboeea1f1da2014-04-02 20:03:32 -060024#include "test.h"
25
Jens Axboef7540862014-02-07 20:52:32 -070026#define CHUNK 131072U
27#define NR_CHUNKS 2048U
Jens Axboefec0f212014-02-07 14:39:33 -070028
29struct test_type {
30 const char *name;
31 unsigned int mask;
Jens Axboe95a5a3f2014-09-27 09:29:42 -060032 void (*fn)(struct test_type *, void *, size_t);
33 uint32_t output;
Jens Axboefec0f212014-02-07 14:39:33 -070034};
35
36enum {
37 T_MD5 = 1U << 0,
38 T_CRC64 = 1U << 1,
39 T_CRC32 = 1U << 2,
40 T_CRC32C = 1U << 3,
41 T_CRC16 = 1U << 4,
42 T_CRC7 = 1U << 5,
43 T_SHA1 = 1U << 6,
44 T_SHA256 = 1U << 7,
45 T_SHA512 = 1U << 8,
Jens Axboe844ea602014-02-20 13:21:45 -080046 T_XXHASH = 1U << 9,
Jens Axboe67c1b7c2014-09-27 08:38:42 -060047 T_MURMUR3 = 1U << 10,
Jens Axboe95a5a3f2014-09-27 09:29:42 -060048 T_JHASH = 1U << 11,
Jens Axboe262cf5c2014-09-27 21:27:48 -060049 T_FNV = 1U << 12,
Jens Axboefec0f212014-02-07 14:39:33 -070050};
51
Jens Axboe95a5a3f2014-09-27 09:29:42 -060052static void t_md5(struct test_type *t, void *buf, size_t size)
Jens Axboefec0f212014-02-07 14:39:33 -070053{
54 uint32_t digest[4];
55 struct fio_md5_ctx ctx = { .hash = digest };
Jens Axboefec0f212014-02-07 14:39:33 -070056 int i;
57
58 fio_md5_init(&ctx);
59
Jens Axboefc18c782014-09-27 14:13:58 -060060 for (i = 0; i < NR_CHUNKS; i++) {
Jens Axboe7e92c712014-07-25 10:12:26 +020061 fio_md5_update(&ctx, buf, size);
Jens Axboefc18c782014-09-27 14:13:58 -060062 fio_md5_final(&ctx);
63 }
Jens Axboe7e92c712014-07-25 10:12:26 +020064}
65
Jens Axboe95a5a3f2014-09-27 09:29:42 -060066static void t_crc64(struct test_type *t, void *buf, size_t size)
Jens Axboe7e92c712014-07-25 10:12:26 +020067{
Jens Axboe7e92c712014-07-25 10:12:26 +020068 int i;
Jens Axboefec0f212014-02-07 14:39:33 -070069
Jens Axboefec0f212014-02-07 14:39:33 -070070 for (i = 0; i < NR_CHUNKS; i++)
Jens Axboe7e92c712014-07-25 10:12:26 +020071 fio_crc64(buf, size);
Jens Axboefec0f212014-02-07 14:39:33 -070072}
73
Jens Axboe95a5a3f2014-09-27 09:29:42 -060074static void t_crc32(struct test_type *t, void *buf, size_t size)
Jens Axboe7e92c712014-07-25 10:12:26 +020075{
Jens Axboe7e92c712014-07-25 10:12:26 +020076 int i;
77
Jens Axboe7e92c712014-07-25 10:12:26 +020078 for (i = 0; i < NR_CHUNKS; i++)
79 fio_crc32(buf, size);
Jens Axboe7e92c712014-07-25 10:12:26 +020080}
81
Jens Axboe95a5a3f2014-09-27 09:29:42 -060082static void t_crc32c(struct test_type *t, void *buf, size_t size)
Jens Axboe7e92c712014-07-25 10:12:26 +020083{
Jens Axboe7e92c712014-07-25 10:12:26 +020084 int i;
85
Jens Axboe7e92c712014-07-25 10:12:26 +020086 for (i = 0; i < NR_CHUNKS; i++)
87 fio_crc32c(buf, size);
Jens Axboe7e92c712014-07-25 10:12:26 +020088}
89
Jens Axboe95a5a3f2014-09-27 09:29:42 -060090static void t_crc16(struct test_type *t, void *buf, size_t size)
Jens Axboe7e92c712014-07-25 10:12:26 +020091{
Jens Axboe7e92c712014-07-25 10:12:26 +020092 int i;
93
Jens Axboe7e92c712014-07-25 10:12:26 +020094 for (i = 0; i < NR_CHUNKS; i++)
95 fio_crc16(buf, size);
Jens Axboe7e92c712014-07-25 10:12:26 +020096}
97
Jens Axboe95a5a3f2014-09-27 09:29:42 -060098static void t_crc7(struct test_type *t, void *buf, size_t size)
Jens Axboefec0f212014-02-07 14:39:33 -070099{
Jens Axboefec0f212014-02-07 14:39:33 -0700100 int i;
101
Jens Axboefec0f212014-02-07 14:39:33 -0700102 for (i = 0; i < NR_CHUNKS; i++)
Jens Axboe7e92c712014-07-25 10:12:26 +0200103 fio_crc7(buf, size);
Jens Axboefec0f212014-02-07 14:39:33 -0700104}
105
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600106static void t_sha1(struct test_type *t, void *buf, size_t size)
Jens Axboefec0f212014-02-07 14:39:33 -0700107{
108 uint32_t sha[5];
109 struct fio_sha1_ctx ctx = { .H = sha };
Jens Axboefec0f212014-02-07 14:39:33 -0700110 int i;
111
112 fio_sha1_init(&ctx);
113
Jens Axboebf2d8162015-01-16 16:10:43 -0700114 for (i = 0; i < NR_CHUNKS; i++) {
Jens Axboe7e92c712014-07-25 10:12:26 +0200115 fio_sha1_update(&ctx, buf, size);
Jens Axboebf2d8162015-01-16 16:10:43 -0700116 fio_sha1_final(&ctx);
117 }
Jens Axboefec0f212014-02-07 14:39:33 -0700118}
119
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600120static void t_sha256(struct test_type *t, void *buf, size_t size)
Jens Axboefec0f212014-02-07 14:39:33 -0700121{
122 uint8_t sha[64];
123 struct fio_sha256_ctx ctx = { .buf = sha };
Jens Axboefec0f212014-02-07 14:39:33 -0700124 int i;
125
126 fio_sha256_init(&ctx);
127
Jens Axboefc18c782014-09-27 14:13:58 -0600128 for (i = 0; i < NR_CHUNKS; i++) {
Jens Axboe7e92c712014-07-25 10:12:26 +0200129 fio_sha256_update(&ctx, buf, size);
Jens Axboefc18c782014-09-27 14:13:58 -0600130 fio_sha256_final(&ctx);
131 }
Jens Axboefec0f212014-02-07 14:39:33 -0700132}
133
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600134static void t_sha512(struct test_type *t, void *buf, size_t size)
Jens Axboefec0f212014-02-07 14:39:33 -0700135{
136 uint8_t sha[128];
137 struct fio_sha512_ctx ctx = { .buf = sha };
Jens Axboefec0f212014-02-07 14:39:33 -0700138 int i;
139
140 fio_sha512_init(&ctx);
141
Jens Axboefec0f212014-02-07 14:39:33 -0700142 for (i = 0; i < NR_CHUNKS; i++)
Jens Axboe7e92c712014-07-25 10:12:26 +0200143 fio_sha512_update(&ctx, buf, size);
Jens Axboefec0f212014-02-07 14:39:33 -0700144}
145
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600146static void t_murmur3(struct test_type *t, void *buf, size_t size)
Jens Axboe67c1b7c2014-09-27 08:38:42 -0600147{
148 int i;
149
150 for (i = 0; i < NR_CHUNKS; i++)
151 murmurhash3(buf, size, 0x8989);
152}
153
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600154static void t_jhash(struct test_type *t, void *buf, size_t size)
155{
156 int i;
157
158 for (i = 0; i < NR_CHUNKS; i++)
159 t->output += jhash(buf, size, 0x8989);
160}
161
Jens Axboe262cf5c2014-09-27 21:27:48 -0600162static void t_fnv(struct test_type *t, void *buf, size_t size)
163{
164 int i;
165
166 for (i = 0; i < NR_CHUNKS; i++)
167 t->output += fnv(buf, size, 0x8989);
168}
169
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600170static void t_xxhash(struct test_type *t, void *buf, size_t size)
Jens Axboe844ea602014-02-20 13:21:45 -0800171{
172 void *state;
Jens Axboe844ea602014-02-20 13:21:45 -0800173 int i;
174
175 state = XXH32_init(0x8989);
176
Jens Axboe844ea602014-02-20 13:21:45 -0800177 for (i = 0; i < NR_CHUNKS; i++)
Jens Axboe7e92c712014-07-25 10:12:26 +0200178 XXH32_update(state, buf, size);
Jens Axboe844ea602014-02-20 13:21:45 -0800179
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600180 t->output = XXH32_digest(state);
Jens Axboe844ea602014-02-20 13:21:45 -0800181}
182
Jens Axboefec0f212014-02-07 14:39:33 -0700183static struct test_type t[] = {
184 {
185 .name = "md5",
186 .mask = T_MD5,
187 .fn = t_md5,
188 },
189 {
190 .name = "crc64",
191 .mask = T_CRC64,
192 .fn = t_crc64,
193 },
194 {
195 .name = "crc32",
196 .mask = T_CRC32,
197 .fn = t_crc32,
198 },
199 {
200 .name = "crc32c",
201 .mask = T_CRC32C,
202 .fn = t_crc32c,
203 },
204 {
205 .name = "crc16",
206 .mask = T_CRC16,
207 .fn = t_crc16,
208 },
209 {
210 .name = "crc7",
211 .mask = T_CRC7,
212 .fn = t_crc7,
213 },
214 {
215 .name = "sha1",
216 .mask = T_SHA1,
217 .fn = t_sha1,
218 },
219 {
220 .name = "sha256",
221 .mask = T_SHA256,
222 .fn = t_sha256,
223 },
224 {
225 .name = "sha512",
226 .mask = T_SHA512,
227 .fn = t_sha512,
228 },
229 {
Jens Axboe844ea602014-02-20 13:21:45 -0800230 .name = "xxhash",
231 .mask = T_XXHASH,
232 .fn = t_xxhash,
233 },
234 {
Jens Axboe67c1b7c2014-09-27 08:38:42 -0600235 .name = "murmur3",
236 .mask = T_MURMUR3,
237 .fn = t_murmur3,
238 },
239 {
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600240 .name = "jhash",
241 .mask = T_JHASH,
242 .fn = t_jhash,
243 },
244 {
Jens Axboe262cf5c2014-09-27 21:27:48 -0600245 .name = "fnv",
246 .mask = T_FNV,
247 .fn = t_fnv,
248 },
249 {
Jens Axboefec0f212014-02-07 14:39:33 -0700250 .name = NULL,
251 },
252};
253
254static unsigned int get_test_mask(const char *type)
255{
256 char *ostr, *str = strdup(type);
257 unsigned int mask;
258 char *name;
259 int i;
260
261 ostr = str;
262 mask = 0;
263 while ((name = strsep(&str, ",")) != NULL) {
264 for (i = 0; t[i].name; i++) {
Jens Axboef7540862014-02-07 20:52:32 -0700265 if (!strcmp(t[i].name, name)) {
Jens Axboefec0f212014-02-07 14:39:33 -0700266 mask |= t[i].mask;
267 break;
268 }
269 }
270 }
271
272 free(ostr);
273 return mask;
274}
275
Jens Axboe782744e2014-02-07 20:54:39 -0700276static int list_types(void)
277{
278 int i;
279
280 for (i = 0; t[i].name; i++)
281 printf("%s\n", t[i].name);
282
Jens Axboe7e92c712014-07-25 10:12:26 +0200283 return 1;
Jens Axboe782744e2014-02-07 20:54:39 -0700284}
285
Jens Axboefec0f212014-02-07 14:39:33 -0700286int fio_crctest(const char *type)
287{
288 unsigned int test_mask = 0;
289 uint64_t mb = CHUNK * NR_CHUNKS;
Jens Axboef8889712014-07-25 15:15:46 +0200290 struct frand_state state;
Jens Axboe7e92c712014-07-25 10:12:26 +0200291 int i, first = 1;
292 void *buf;
Jens Axboefec0f212014-02-07 14:39:33 -0700293
294 crc32c_intel_probe();
295
296 if (!type)
297 test_mask = ~0U;
Jens Axboe782744e2014-02-07 20:54:39 -0700298 else if (!strcmp(type, "help") || !strcmp(type, "list"))
299 return list_types();
Jens Axboefec0f212014-02-07 14:39:33 -0700300 else
301 test_mask = get_test_mask(type);
302
Jens Axboe7e92c712014-07-25 10:12:26 +0200303 if (!test_mask) {
304 fprintf(stderr, "fio: unknown hash `%s`. Available:\n", type);
305 return list_types();
306 }
307
308 buf = malloc(CHUNK);
Jens Axboef8889712014-07-25 15:15:46 +0200309 init_rand_seed(&state, 0x8989);
310 fill_random_buf(&state, buf, CHUNK);
Jens Axboe7e92c712014-07-25 10:12:26 +0200311
Jens Axboefec0f212014-02-07 14:39:33 -0700312 for (i = 0; t[i].name; i++) {
Jens Axboef8889712014-07-25 15:15:46 +0200313 struct timeval tv;
Jens Axboefec0f212014-02-07 14:39:33 -0700314 double mb_sec;
315 uint64_t usec;
Jens Axboe3e6d4152014-09-27 08:43:27 -0600316 char pre[3];
Jens Axboefec0f212014-02-07 14:39:33 -0700317
318 if (!(t[i].mask & test_mask))
319 continue;
320
Jens Axboef8889712014-07-25 15:15:46 +0200321 /*
322 * For first run, make sure CPUs are spun up and that
323 * we've touched the data.
324 */
325 if (first) {
326 usec_spin(100000);
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600327 t[i].fn(&t[i], buf, CHUNK);
Jens Axboef8889712014-07-25 15:15:46 +0200328 }
329
330 fio_gettime(&tv, NULL);
Jens Axboe95a5a3f2014-09-27 09:29:42 -0600331 t[i].fn(&t[i], buf, CHUNK);
Jens Axboef8889712014-07-25 15:15:46 +0200332 usec = utime_since_now(&tv);
Jens Axboe7e92c712014-07-25 10:12:26 +0200333
Jens Axboe7b3aea92014-10-14 19:47:41 -0600334 if (usec) {
335 mb_sec = (double) mb / (double) usec;
336 mb_sec /= (1.024 * 1.024);
337 if (strlen(t[i].name) >= 7)
338 sprintf(pre, "\t");
339 else
340 sprintf(pre, "\t\t");
341 printf("%s:%s%8.2f MB/sec\n", t[i].name, pre, mb_sec);
342 } else
343 printf("%s:inf MB/sec\n", t[i].name);
Jens Axboe7e92c712014-07-25 10:12:26 +0200344 first = 0;
Jens Axboefec0f212014-02-07 14:39:33 -0700345 }
Jens Axboe782744e2014-02-07 20:54:39 -0700346
Jens Axboe7e92c712014-07-25 10:12:26 +0200347 free(buf);
Jens Axboefec0f212014-02-07 14:39:33 -0700348 return 0;
349}