Bitcoin Core  27.99.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 <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  });
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  });
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  });
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  });
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 
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  });
103 }
104 
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  });
115 }
116 
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  });
127 }
128 
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  });
139 }
140 
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  });
149 }
150 
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  });
159 }
160 
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  });
169 }
170 
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  });
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 
200 {
201  FastRandomContext rng(true);
202  bench.run([&] {
203  rng.rand32();
204  });
205 }
206 
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 
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 
267 
279 
A hasher class for RIPEMD-160.
Definition: ripemd160.h:13
CRIPEMD160 & Write(const unsigned char *data, size_t len)
Definition: ripemd160.cpp:247
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: ripemd160.cpp:273
static const size_t OUTPUT_SIZE
Definition: ripemd160.h:20
A hasher class for SHA1.
Definition: sha1.h:13
CSHA1 & Write(const unsigned char *data, size_t len)
Definition: sha1.cpp:154
static const size_t OUTPUT_SIZE
Definition: sha1.h:20
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha1.cpp:180
A hasher class for SHA-256.
Definition: sha256.h:14
static const size_t OUTPUT_SIZE
Definition: sha256.h:21
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:728
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:702
A hasher class for SHA-512.
Definition: sha512.h:13
static constexpr size_t OUTPUT_SIZE
Definition: sha512.h:20
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha512.cpp:185
CSHA512 & Write(const unsigned char *data, size_t len)
Definition: sha512.cpp:159
Fast randomness source.
Definition: random.h:145
uint32_t rand32() noexcept
Generate a random 32-bit integer.
Definition: random.h:222
bool randbool() noexcept
Generate a random boolean.
Definition: random.h:228
std::vector< B > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:673
A class representing MuHash sets.
Definition: muhash.h:91
Definition: sha3.h:17
SHA3_256 & Write(Span< const unsigned char > data)
Definition: sha3.cpp:106
SHA3_256 & Finalize(Span< unsigned char > output)
Definition: sha3.cpp:136
static constexpr size_t OUTPUT_SIZE
Definition: sha3.h:33
Main entry point to nanobench's benchmarking facility.
Definition: nanobench.h:627
Bench & run(char const *benchmarkName, Op &&op)
Repeatedly calls op() based on the configuration, and performs measurements.
Definition: nanobench.h:1234
Bench & batch(T b) noexcept
Sets the batch size.
Definition: nanobench.h:1258
ANKERL_NANOBENCH(NODISCARD) std Bench & name(char const *benchmarkName)
Gets the title of the benchmark.
Bench & unit(char const *unit)
Sets the operation unit.
constexpr unsigned char * begin()
Definition: uint256.h:68
256-bit opaque blob.
Definition: uint256.h:106
static void SipHash_32b(benchmark::Bench &bench)
static void SHA256_STANDARD(benchmark::Bench &bench)
Definition: crypto_hash.cpp:40
static void SHA256_SHANI(benchmark::Bench &bench)
Definition: crypto_hash.cpp:73
static void FastRandom_1bit(benchmark::Bench &bench)
static void MuHashPrecompute(benchmark::Bench &bench)
static const uint64_t BUFFER_SIZE
Definition: crypto_hash.cpp:20
BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH)
static void SHA256_32b_AVX2(benchmark::Bench &bench)
static void SHA256D64_1024_SHANI(benchmark::Bench &bench)
static void SHA256_AVX2(benchmark::Bench &bench)
Definition: crypto_hash.cpp:62
static void SHA256_32b_SHANI(benchmark::Bench &bench)
static void SHA256_32b_SSE4(benchmark::Bench &bench)
static void SHA256D64_1024_AVX2(benchmark::Bench &bench)
static void SHA256D64_1024_STANDARD(benchmark::Bench &bench)
static void FastRandom_32bit(benchmark::Bench &bench)
static void MuHashMul(benchmark::Bench &bench)
static void SHA256_SSE4(benchmark::Bench &bench)
Definition: crypto_hash.cpp:51
static void BenchRIPEMD160(benchmark::Bench &bench)
Definition: crypto_hash.cpp:22
static void SHA3_256_1M(benchmark::Bench &bench)
Definition: crypto_hash.cpp:84
static void SHA1(benchmark::Bench &bench)
Definition: crypto_hash.cpp:31
static void SHA512(benchmark::Bench &bench)
static void MuHashDiv(benchmark::Bench &bench)
static void MuHash(benchmark::Bench &bench)
static void SHA256D64_1024_SSE4(benchmark::Bench &bench)
static void SHA256_32b_STANDARD(benchmark::Bench &bench)
Definition: crypto_hash.cpp:93
@ HIGH
Definition: bench.h:47
void SHA256D64(unsigned char *out, const unsigned char *in, size_t blocks)
Compute multiple double-SHA256's of 64-byte blobs.
Definition: sha256.cpp:752
std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implementation)
Autodetect the best available SHA256 implementation.
Definition: sha256.cpp:588
uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256 &val)
Optimized SipHash-2-4 implementation for uint256.
Definition: siphash.cpp:95
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1162