/ src / bench / crypto_hash.cpp
crypto_hash.cpp
  1  // Copyright (c) 2016-present The Bitcoin Core 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      PresaltedSipHasher presalted_sip_hasher(rng.rand64(), rng.rand64());
197      auto val{rng.rand256()};
198      auto i{0U};
199      bench.run([&] {
200          ankerl::nanobench::doNotOptimizeAway(presalted_sip_hasher(val));
201          ++i;
202          val.data()[i % uint256::size()] ^= i & 0xFF;
203      });
204  }
205  
206  static void MuHash(benchmark::Bench& bench)
207  {
208      MuHash3072 acc;
209      unsigned char key[32] = {0};
210      uint32_t i = 0;
211      bench.run([&] {
212          key[0] = ++i & 0xFF;
213          acc *= MuHash3072(key);
214      });
215  }
216  
217  static void MuHashMul(benchmark::Bench& bench)
218  {
219      MuHash3072 acc;
220      FastRandomContext rng(true);
221      MuHash3072 muhash{rng.randbytes(32)};
222  
223      bench.run([&] {
224          acc *= muhash;
225      });
226  }
227  
228  static void MuHashDiv(benchmark::Bench& bench)
229  {
230      MuHash3072 acc;
231      FastRandomContext rng(true);
232      MuHash3072 muhash{rng.randbytes(32)};
233  
234      bench.run([&] {
235          acc /= muhash;
236      });
237  }
238  
239  static void MuHashPrecompute(benchmark::Bench& bench)
240  {
241      MuHash3072 acc;
242      FastRandomContext rng(true);
243      std::vector<unsigned char> key{rng.randbytes(32)};
244  
245      bench.run([&] {
246          MuHash3072{key};
247      });
248  }
249  
250  static void MuHashFinalize(benchmark::Bench& bench)
251  {
252      FastRandomContext rng(true);
253      MuHash3072 acc{rng.randbytes(32)};
254      acc /= MuHash3072{rng.rand256()};
255  
256      bench.run([&] {
257          uint256 out;
258          acc.Finalize(out);
259          acc /= MuHash3072{out};
260      });
261  }
262  
263  BENCHMARK(BenchRIPEMD160);
264  BENCHMARK(SHA1);
265  BENCHMARK(SHA256_STANDARD);
266  BENCHMARK(SHA256_SSE4);
267  BENCHMARK(SHA256_AVX2);
268  BENCHMARK(SHA256_SHANI);
269  BENCHMARK(SHA512);
270  BENCHMARK(SHA3_256_1M);
271  
272  BENCHMARK(SHA256_32b_STANDARD);
273  BENCHMARK(SHA256_32b_SSE4);
274  BENCHMARK(SHA256_32b_AVX2);
275  BENCHMARK(SHA256_32b_SHANI);
276  BENCHMARK(SipHash_32b);
277  BENCHMARK(SHA256D64_1024_STANDARD);
278  BENCHMARK(SHA256D64_1024_SSE4);
279  BENCHMARK(SHA256D64_1024_AVX2);
280  BENCHMARK(SHA256D64_1024_SHANI);
281  
282  BENCHMARK(MuHash);
283  BENCHMARK(MuHashMul);
284  BENCHMARK(MuHashDiv);
285  BENCHMARK(MuHashPrecompute);
286  BENCHMARK(MuHashFinalize);