btrfs-progs/crypto/hash-speedtest.c
David Sterba 34ef695a81 btrfs-progs: add BLAKE2 to hash-speedtest
Sample results, Intel(R) Xeon(R) CPU E5-1620 v3 @ 3.50GHz

Block size: 4096
Iterations: 1000000

    NULL-NOP: cycles:    314296257, c/i      314
 NULL-MEMCPY: cycles:    582807266, c/i      582
      CRC32C: cycles:   1738544130, c/i     1738
      XXHASH: cycles:   1449519934, c/i     1449
      SHA256: cycles: 110648340548, c/i   110648
     BLAKE2b: cycles:  29743769472, c/i    29743

Note this is unoptimized reference implementation.

Signed-off-by: David Sterba <dsterba@suse.com>
2019-11-18 19:21:06 +01:00

105 lines
2.4 KiB
C

#include "../kerncompat.h"
#include "crypto/hash.h"
#include "crypto/crc32c.h"
#include "crypto/sha.h"
#include "crypto/blake2.h"
#ifndef __x86_64__
#error "Only x86_64 supported"
#endif
const int blocksize = 4096;
int iterations = 100000;
static __always_inline unsigned long long rdtsc(void)
{
unsigned low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
return (low | ((u64)(high) << 32));
}
static inline u64 read_tsc(void)
{
asm volatile("mfence");
return rdtsc();
}
/* Read the input and copy last bytes as the hash */
static int hash_null_memcpy(const u8 *buf, size_t length, u8 *out)
{
const u8 *end = buf + length;
while (buf + CRYPTO_HASH_SIZE_MAX < end) {
memcpy(out, buf, CRYPTO_HASH_SIZE_MAX);
buf += CRYPTO_HASH_SIZE_MAX;
}
return 0;
}
/* Test overhead of the calls */
static int hash_null_nop(const u8 *buf, size_t length, u8 *out)
{
memset(out, 0xFF, CRYPTO_HASH_SIZE_MAX);
return 0;
}
int main(int argc, char **argv) {
u8 buf[blocksize];
u8 hash[32];
int idx;
int iter;
struct contestant {
char name[16];
int (*digest)(const u8 *buf, size_t length, u8 *out);
int digest_size;
u64 cycles;
} contestants[] = {
{ .name = "NULL-NOP", .digest = hash_null_nop, .digest_size = 32 },
{ .name = "NULL-MEMCPY", .digest = hash_null_memcpy, .digest_size = 32 },
{ .name = "CRC32C", .digest = hash_crc32c, .digest_size = 4 },
{ .name = "XXHASH", .digest = hash_xxhash, .digest_size = 8 },
{ .name = "SHA256", .digest = hash_sha256, .digest_size = 32 },
{ .name = "BLAKE2b", .digest = hash_blake2b, .digest_size = 32 },
};
if (argc > 1) {
iterations = atoi(argv[1]);
if (iterations < 0)
iterations = 1;
}
crc32c_optimization_init();
memset(buf, 0, 4096);
printf("Block size: %d\n", blocksize);
printf("Iterations: %d\n", iterations);
printf("\n");
for (idx = 0; idx < ARRAY_SIZE(contestants); idx++) {
struct contestant *c = &contestants[idx];
u64 start, end;
printf("% 12s: ", c->name);
fflush(stdout);
start = read_tsc();
for (iter = 0; iter < iterations; iter++) {
memset(buf, iter & 0xFF, blocksize);
memset(hash, 0, 32);
c->digest(buf, blocksize, hash);
}
end = read_tsc();
c->cycles = end - start;
printf("cycles: % 12llu, c/i % 8llu\n",
(unsigned long long)c->cycles,
(unsigned long long)c->cycles / iterations);
}
return 0;
}