crypto_hash.cpp raw

   1  // Copyright (c) 2016-2022 The Limenka developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  
   6  #include <bench/bench.h>
   7  #include <crypto/muhash.h>
   8  #include <crypto/ripemd160.h>
   9  #include <crypto/sha1.h>
  10  #include <crypto/sha256.h>
  11  #include <crypto/sha3.h>
  12  #include <crypto/sha512.h>
  13  #include <crypto/siphash.h>
  14  #include <random.h>
  15  #include <span.h>
  16  #include <tinyformat.h>
  17  #include <uint256.h>
  18  
  19  #include <cstdint>
  20  #include <vector>
  21  
  22  /* Number of bytes to hash per iteration */
  23  static const uint64_t BUFFER_SIZE = 1000*1000;
  24  
  25  static void BenchRIPEMD160(benchmark::Bench& bench)
  26  {
  27      uint8_t hash[CRIPEMD160::OUTPUT_SIZE];
  28      std::vector<uint8_t> in(BUFFER_SIZE,0);
  29      bench.batch(in.size()).unit("byte").run([&] {
  30          CRIPEMD160().Write(in.data(), in.size()).Finalize(hash);
  31      });
  32  }
  33  
  34  static void SHA1(benchmark::Bench& bench)
  35  {
  36      uint8_t hash[CSHA1::OUTPUT_SIZE];
  37      std::vector<uint8_t> in(BUFFER_SIZE,0);
  38      bench.batch(in.size()).unit("byte").run([&] {
  39          CSHA1().Write(in.data(), in.size()).Finalize(hash);
  40      });
  41  }
  42  
  43  static void SHA256_STANDARD(benchmark::Bench& bench)
  44  {
  45      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::STANDARD)));
  46      uint8_t hash[CSHA256::OUTPUT_SIZE];
  47      std::vector<uint8_t> in(BUFFER_SIZE,0);
  48      bench.batch(in.size()).unit("byte").run([&] {
  49          CSHA256().Write(in.data(), in.size()).Finalize(hash);
  50      });
  51      SHA256AutoDetect();
  52  }
  53  
  54  static void SHA256_SSE4(benchmark::Bench& bench)
  55  {
  56      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4)));
  57      uint8_t hash[CSHA256::OUTPUT_SIZE];
  58      std::vector<uint8_t> in(BUFFER_SIZE,0);
  59      bench.batch(in.size()).unit("byte").run([&] {
  60          CSHA256().Write(in.data(), in.size()).Finalize(hash);
  61      });
  62      SHA256AutoDetect();
  63  }
  64  
  65  static void SHA256_AVX2(benchmark::Bench& bench)
  66  {
  67      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_AVX2)));
  68      uint8_t hash[CSHA256::OUTPUT_SIZE];
  69      std::vector<uint8_t> in(BUFFER_SIZE,0);
  70      bench.batch(in.size()).unit("byte").run([&] {
  71          CSHA256().Write(in.data(), in.size()).Finalize(hash);
  72      });
  73      SHA256AutoDetect();
  74  }
  75  
  76  static void SHA256_SHANI(benchmark::Bench& bench)
  77  {
  78      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_SHANI)));
  79      uint8_t hash[CSHA256::OUTPUT_SIZE];
  80      std::vector<uint8_t> in(BUFFER_SIZE,0);
  81      bench.batch(in.size()).unit("byte").run([&] {
  82          CSHA256().Write(in.data(), in.size()).Finalize(hash);
  83      });
  84      SHA256AutoDetect();
  85  }
  86  
  87  static void SHA3_256_1M(benchmark::Bench& bench)
  88  {
  89      uint8_t hash[SHA3_256::OUTPUT_SIZE];
  90      std::vector<uint8_t> in(BUFFER_SIZE,0);
  91      bench.batch(in.size()).unit("byte").run([&] {
  92          SHA3_256().Write(in).Finalize(hash);
  93      });
  94  }
  95  
  96  static void SHA256_32b_STANDARD(benchmark::Bench& bench)
  97  {
  98      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::STANDARD)));
  99      std::vector<uint8_t> in(32,0);
 100      bench.batch(in.size()).unit("byte").run([&] {
 101          CSHA256()
 102              .Write(in.data(), in.size())
 103              .Finalize(in.data());
 104      });
 105      SHA256AutoDetect();
 106  }
 107  
 108  static void SHA256_32b_SSE4(benchmark::Bench& bench)
 109  {
 110      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4)));
 111      std::vector<uint8_t> in(32,0);
 112      bench.batch(in.size()).unit("byte").run([&] {
 113          CSHA256()
 114              .Write(in.data(), in.size())
 115              .Finalize(in.data());
 116      });
 117      SHA256AutoDetect();
 118  }
 119  
 120  static void SHA256_32b_AVX2(benchmark::Bench& bench)
 121  {
 122      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_AVX2)));
 123      std::vector<uint8_t> in(32,0);
 124      bench.batch(in.size()).unit("byte").run([&] {
 125          CSHA256()
 126              .Write(in.data(), in.size())
 127              .Finalize(in.data());
 128      });
 129      SHA256AutoDetect();
 130  }
 131  
 132  static void SHA256_32b_SHANI(benchmark::Bench& bench)
 133  {
 134      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_SHANI)));
 135      std::vector<uint8_t> in(32,0);
 136      bench.batch(in.size()).unit("byte").run([&] {
 137          CSHA256()
 138              .Write(in.data(), in.size())
 139              .Finalize(in.data());
 140      });
 141      SHA256AutoDetect();
 142  }
 143  
 144  static void SHA256D64_1024_STANDARD(benchmark::Bench& bench)
 145  {
 146      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::STANDARD)));
 147      std::vector<uint8_t> in(64 * 1024, 0);
 148      bench.batch(in.size()).unit("byte").run([&] {
 149          SHA256D64(in.data(), in.data(), 1024);
 150      });
 151      SHA256AutoDetect();
 152  }
 153  
 154  static void SHA256D64_1024_SSE4(benchmark::Bench& bench)
 155  {
 156      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4)));
 157      std::vector<uint8_t> in(64 * 1024, 0);
 158      bench.batch(in.size()).unit("byte").run([&] {
 159          SHA256D64(in.data(), in.data(), 1024);
 160      });
 161      SHA256AutoDetect();
 162  }
 163  
 164  static void SHA256D64_1024_AVX2(benchmark::Bench& bench)
 165  {
 166      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_AVX2)));
 167      std::vector<uint8_t> in(64 * 1024, 0);
 168      bench.batch(in.size()).unit("byte").run([&] {
 169          SHA256D64(in.data(), in.data(), 1024);
 170      });
 171      SHA256AutoDetect();
 172  }
 173  
 174  static void SHA256D64_1024_SHANI(benchmark::Bench& bench)
 175  {
 176      bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_SHANI)));
 177      std::vector<uint8_t> in(64 * 1024, 0);
 178      bench.batch(in.size()).unit("byte").run([&] {
 179          SHA256D64(in.data(), in.data(), 1024);
 180      });
 181      SHA256AutoDetect();
 182  }
 183  
 184  static void SHA512(benchmark::Bench& bench)
 185  {
 186      uint8_t hash[CSHA512::OUTPUT_SIZE];
 187      std::vector<uint8_t> in(BUFFER_SIZE,0);
 188      bench.batch(in.size()).unit("byte").run([&] {
 189          CSHA512().Write(in.data(), in.size()).Finalize(hash);
 190      });
 191  }
 192  
 193  static void SipHash_32b(benchmark::Bench& bench)
 194  {
 195      FastRandomContext rng{/*fDeterministic=*/true};
 196      auto k0{rng.rand64()}, k1{rng.rand64()};
 197      auto val{rng.rand256()};
 198      auto i{0U};
 199      bench.run([&] {
 200          ankerl::nanobench::doNotOptimizeAway(SipHashUint256(k0, k1, val));
 201          ++k0;
 202          ++k1;
 203          ++i;
 204          val.data()[i % uint256::size()] ^= i & 0xFF;
 205      });
 206  }
 207  
 208  static void MuHash(benchmark::Bench& bench)
 209  {
 210      MuHash3072 acc;
 211      unsigned char key[32] = {0};
 212      uint32_t i = 0;
 213      bench.run([&] {
 214          key[0] = ++i & 0xFF;
 215          acc *= MuHash3072(key);
 216      });
 217  }
 218  
 219  static void MuHashMul(benchmark::Bench& bench)
 220  {
 221      MuHash3072 acc;
 222      FastRandomContext rng(true);
 223      MuHash3072 muhash{rng.randbytes(32)};
 224  
 225      bench.run([&] {
 226          acc *= muhash;
 227      });
 228  }
 229  
 230  static void MuHashDiv(benchmark::Bench& bench)
 231  {
 232      MuHash3072 acc;
 233      FastRandomContext rng(true);
 234      MuHash3072 muhash{rng.randbytes(32)};
 235  
 236      bench.run([&] {
 237          acc /= muhash;
 238      });
 239  }
 240  
 241  static void MuHashPrecompute(benchmark::Bench& bench)
 242  {
 243      MuHash3072 acc;
 244      FastRandomContext rng(true);
 245      std::vector<unsigned char> key{rng.randbytes(32)};
 246  
 247      bench.run([&] {
 248          MuHash3072{key};
 249      });
 250  }
 251  
 252  static void MuHashFinalize(benchmark::Bench& bench)
 253  {
 254      FastRandomContext rng(true);
 255      MuHash3072 acc{rng.randbytes(32)};
 256      acc /= MuHash3072{rng.rand256()};
 257  
 258      bench.run([&] {
 259          uint256 out;
 260          acc.Finalize(out);
 261          acc /= MuHash3072{out};
 262      });
 263  }
 264  
 265  BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH);
 266  BENCHMARK(SHA1, benchmark::PriorityLevel::HIGH);
 267  BENCHMARK(SHA256_STANDARD, benchmark::PriorityLevel::HIGH);
 268  BENCHMARK(SHA256_SSE4, benchmark::PriorityLevel::HIGH);
 269  BENCHMARK(SHA256_AVX2, benchmark::PriorityLevel::HIGH);
 270  BENCHMARK(SHA256_SHANI, benchmark::PriorityLevel::HIGH);
 271  BENCHMARK(SHA512, benchmark::PriorityLevel::HIGH);
 272  BENCHMARK(SHA3_256_1M, benchmark::PriorityLevel::HIGH);
 273  
 274  BENCHMARK(SHA256_32b_STANDARD, benchmark::PriorityLevel::HIGH);
 275  BENCHMARK(SHA256_32b_SSE4, benchmark::PriorityLevel::HIGH);
 276  BENCHMARK(SHA256_32b_AVX2, benchmark::PriorityLevel::HIGH);
 277  BENCHMARK(SHA256_32b_SHANI, benchmark::PriorityLevel::HIGH);
 278  BENCHMARK(SipHash_32b, benchmark::PriorityLevel::HIGH);
 279  BENCHMARK(SHA256D64_1024_STANDARD, benchmark::PriorityLevel::HIGH);
 280  BENCHMARK(SHA256D64_1024_SSE4, benchmark::PriorityLevel::HIGH);
 281  BENCHMARK(SHA256D64_1024_AVX2, benchmark::PriorityLevel::HIGH);
 282  BENCHMARK(SHA256D64_1024_SHANI, benchmark::PriorityLevel::HIGH);
 283  
 284  BENCHMARK(MuHash, benchmark::PriorityLevel::HIGH);
 285  BENCHMARK(MuHashMul, benchmark::PriorityLevel::HIGH);
 286  BENCHMARK(MuHashDiv, benchmark::PriorityLevel::HIGH);
 287  BENCHMARK(MuHashPrecompute, benchmark::PriorityLevel::HIGH);
 288  BENCHMARK(MuHashFinalize, benchmark::PriorityLevel::HIGH);
 289