Home | History | Annotate | Download | only in crc
      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%.2f MB/sec\n", t[i].name, mb_sec);
    377 	}
    378 
    379 	return 0;
    380 }
    381