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