C++程序  |  381行  |  5.83 KB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../fio.h"
#include "../gettime.h"
#include "../fio_time.h"
#include "../verify.h"

#include "../crc/md5.h"
#include "../crc/crc64.h"
#include "../crc/crc32.h"
#include "../crc/crc32c.h"
#include "../crc/crc16.h"
#include "../crc/crc7.h"
#include "../crc/sha1.h"
#include "../crc/sha256.h"
#include "../crc/sha512.h"
#include "../crc/xxhash.h"

#include "test.h"

#define CHUNK		131072U
#define NR_CHUNKS	  2048U

struct test_type {
	const char *name;
	unsigned int mask;
	uint64_t (*fn)(void);
};

enum {
	T_MD5		= 1U << 0,
	T_CRC64		= 1U << 1,
	T_CRC32		= 1U << 2,
	T_CRC32C	= 1U << 3,
	T_CRC16		= 1U << 4,
	T_CRC7		= 1U << 5,
	T_SHA1		= 1U << 6,
	T_SHA256	= 1U << 7,
	T_SHA512	= 1U << 8,
	T_XXHASH	= 1U << 9,
};

static void randomize_buf(void *buf, unsigned int size, int seed)
{
	struct frand_state state;

	init_rand_seed(&state, seed);
	fill_random_buf(&state, buf, size);
}

static uint64_t t_md5(void)
{
	uint32_t digest[4];
	struct fio_md5_ctx ctx = { .hash = digest };
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	fio_md5_init(&ctx);

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_md5_update(&ctx, buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_crc64(void)
{
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_crc64(buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_crc32(void)
{
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_crc32(buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_crc32c(void)
{
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_crc32c(buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_crc16(void)
{
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_crc16(buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_crc7(void)
{
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_crc7(buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_sha1(void)
{
	uint32_t sha[5];
	struct fio_sha1_ctx ctx = { .H = sha };
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	fio_sha1_init(&ctx);

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_sha1_update(&ctx, buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_sha256(void)
{
	uint8_t sha[64];
	struct fio_sha256_ctx ctx = { .buf = sha };
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	fio_sha256_init(&ctx);

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_sha256_update(&ctx, buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_sha512(void)
{
	uint8_t sha[128];
	struct fio_sha512_ctx ctx = { .buf = sha };
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	fio_sha512_init(&ctx);

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		fio_sha512_update(&ctx, buf, CHUNK);

	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static uint64_t t_xxhash(void)
{
	void *state;
	struct timeval s;
	uint64_t ret;
	void *buf;
	int i;

	state = XXH32_init(0x8989);

	buf = malloc(CHUNK);
	randomize_buf(buf, CHUNK, 0x8989);

	fio_gettime(&s, NULL);
	for (i = 0; i < NR_CHUNKS; i++)
		XXH32_update(state, buf, CHUNK);

	XXH32_digest(state);
	ret = utime_since_now(&s);
	free(buf);
	return ret;
}

static struct test_type t[] = {
	{
		.name = "md5",
		.mask = T_MD5,
		.fn = t_md5,
	},
	{
		.name = "crc64",
		.mask = T_CRC64,
		.fn = t_crc64,
	},
	{
		.name = "crc32",
		.mask = T_CRC32,
		.fn = t_crc32,
	},
	{
		.name = "crc32c",
		.mask = T_CRC32C,
		.fn = t_crc32c,
	},
	{
		.name = "crc16",
		.mask = T_CRC16,
		.fn = t_crc16,
	},
	{
		.name = "crc7",
		.mask = T_CRC7,
		.fn = t_crc7,
	},
	{
		.name = "sha1",
		.mask = T_SHA1,
		.fn = t_sha1,
	},
	{
		.name = "sha256",
		.mask = T_SHA256,
		.fn = t_sha256,
	},
	{
		.name = "sha512",
		.mask = T_SHA512,
		.fn = t_sha512,
	},
	{
		.name = "xxhash",
		.mask = T_XXHASH,
		.fn = t_xxhash,
	},
	{
		.name = NULL,
	},
};

static unsigned int get_test_mask(const char *type)
{
	char *ostr, *str = strdup(type);
	unsigned int mask;
	char *name;
	int i;

	ostr = str;
	mask = 0;
	while ((name = strsep(&str, ",")) != NULL) {
		for (i = 0; t[i].name; i++) {
			if (!strcmp(t[i].name, name)) {
				mask |= t[i].mask;
				break;
			}
		}
	}

	free(ostr);
	return mask;
}

static int list_types(void)
{
	int i;

	for (i = 0; t[i].name; i++)
		printf("%s\n", t[i].name);

	return 0;
}

int fio_crctest(const char *type)
{
	unsigned int test_mask = 0;
	uint64_t mb = CHUNK * NR_CHUNKS;
	int i;

	crc32c_intel_probe();

	if (!type)
		test_mask = ~0U;
	else if (!strcmp(type, "help") || !strcmp(type, "list"))
		return list_types();
	else
		test_mask = get_test_mask(type);

	for (i = 0; t[i].name; i++) {
		double mb_sec;
		uint64_t usec;

		if (!(t[i].mask & test_mask))
			continue;

		usec = t[i].fn();
		mb_sec = (double) mb / (double) usec;
		mb_sec /= (1.024 * 1.024);
		printf("%s:\t%.2f MB/sec\n", t[i].name, mb_sec);
	}

	return 0;
}