Bitcoin Core  29.1.0
P2P Digital Currency
crypto_hash.cpp
Go to the documentation of this file.
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 <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  });
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  });
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  });
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  });
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 
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  });
106 }
107 
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  });
118 }
119 
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  });
130 }
131 
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  });
142 }
143 
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  });
152 }
153 
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  });
162 }
163 
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  });
172 }
173 
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  });
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([&] {
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 
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 
273 
283 
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition: random.h:297
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:701
uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256 &val)
Optimized SipHash-2-4 implementation for uint256.
Definition: siphash.cpp:95
std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implementation)
Autodetect the best available SHA256 implementation.
Definition: sha256.cpp:587
SHA3_256 & Write(Span< const unsigned char > data)
Definition: sha3.cpp:106
CSHA1 & Write(const unsigned char *data, size_t len)
Definition: sha1.cpp:154
static void SHA256_32b_STANDARD(benchmark::Bench &bench)
Definition: crypto_hash.cpp:96
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172
static void SHA256_STANDARD(benchmark::Bench &bench)
Definition: crypto_hash.cpp:43
static void MuHashPrecompute(benchmark::Bench &bench)
static constexpr unsigned int size()
Definition: uint256.h:121
static void SHA1(benchmark::Bench &bench)
Definition: crypto_hash.cpp:34
Definition: sha3.h:16
static void SHA256_SSE4(benchmark::Bench &bench)
Definition: crypto_hash.cpp:54
static void SipHash_32b(benchmark::Bench &bench)
static constexpr size_t OUTPUT_SIZE
Definition: sha3.h:33
static void MuHashMul(benchmark::Bench &bench)
static void SHA256D64_1024_AVX2(benchmark::Bench &bench)
static void SHA256_SHANI(benchmark::Bench &bench)
Definition: crypto_hash.cpp:76
SHA3_256 & Finalize(Span< unsigned char > output)
Definition: sha3.cpp:136
static void SHA256D64_1024_STANDARD(benchmark::Bench &bench)
static const uint64_t BUFFER_SIZE
Definition: crypto_hash.cpp:23
ANKERL_NANOBENCH(NODISCARD) std Bench & name(char const *benchmarkName)
Gets the title of the benchmark.
BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH)
static void SHA256D64_1024_SSE4(benchmark::Bench &bench)
static void BenchRIPEMD160(benchmark::Bench &bench)
Definition: crypto_hash.cpp:25
Bench & run(char const *benchmarkName, Op &&op)
Repeatedly calls op() based on the configuration, and performs measurements.
Definition: nanobench.h:1234
static void SHA256_AVX2(benchmark::Bench &bench)
Definition: crypto_hash.cpp:65
static const size_t OUTPUT_SIZE
Definition: ripemd160.h:20
void doNotOptimizeAway(Arg &&arg)
Makes sure none of the given arguments are optimized away by the compiler.
Definition: nanobench.h:1279
static void SHA256_32b_SHANI(benchmark::Bench &bench)
Fast randomness source.
Definition: random.h:376
static void MuHashDiv(benchmark::Bench &bench)
static void MuHash(benchmark::Bench &bench)
static void SHA3_256_1M(benchmark::Bench &bench)
Definition: crypto_hash.cpp:87
static constexpr size_t OUTPUT_SIZE
Definition: sha512.h:20
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
static void SHA256D64_1024_SHANI(benchmark::Bench &bench)
static void SHA256_32b_AVX2(benchmark::Bench &bench)
256-bit opaque blob.
Definition: uint256.h:201
uint256 rand256() noexcept
generate a random uint256.
Definition: random.h:308
CSHA512 & Write(const unsigned char *data, size_t len)
Definition: sha512.cpp:159
static const size_t OUTPUT_SIZE
Definition: sha256.h:21
A hasher class for SHA1.
Definition: sha1.h:12
A class representing MuHash sets.
Definition: muhash.h:99
static void MuHashFinalize(benchmark::Bench &bench)
Main entry point to nanobench&#39;s benchmarking facility.
Definition: nanobench.h:627
Bench & batch(T b) noexcept
Sets the batch size.
Definition: nanobench.h:1258
static void SHA256_32b_SSE4(benchmark::Bench &bench)
static void SHA512(benchmark::Bench &bench)
void SHA256D64(unsigned char *out, const unsigned char *in, size_t blocks)
Compute multiple double-SHA256&#39;s of 64-byte blobs.
Definition: sha256.cpp:751
A hasher class for SHA-512.
Definition: sha512.h:12
static const size_t OUTPUT_SIZE
Definition: sha1.h:20
A hasher class for SHA-256.
Definition: sha256.h:13
uint64_t rand64() noexcept
Generate a random 64-bit integer.
Definition: random.h:395
A hasher class for RIPEMD-160.
Definition: ripemd160.h:12