Bitcoin Core 30.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 <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 */
23static const uint64_t BUFFER_SIZE = 1000*1000;
24
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
34static 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
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
54static 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
65static 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
76static 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
87static 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
184static 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
193static 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
206static 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
217static 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
228static 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
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
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
271
281
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:725
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:699
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:386
A class representing MuHash sets.
Definition: muhash.h:103
Optimized SipHash-2-4 implementation for uint256.
Definition: siphash.h:56
uint256 rand256() noexcept
generate a random uint256.
Definition: random.h:317
std::vector< B > randbytes(size_t len) noexcept
Generate random bytes.
Definition: random.h:297
Definition: sha3.h:16
SHA3_256 & Write(std::span< const unsigned char > data)
Definition: sha3.cpp:105
SHA3_256 & Finalize(std::span< unsigned char > output)
Definition: sha3.cpp:135
static constexpr size_t OUTPUT_SIZE
Definition: sha3.h:32
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
ANKERL_NANOBENCH(NODISCARD) std Bench & name(char const *benchmarkName)
Gets the title of the benchmark.
Bench & batch(T b) noexcept
Sets the batch size.
Definition: nanobench.h:1258
Bench & unit(char const *unit)
Sets the operation unit.
static constexpr unsigned int size()
Definition: uint256.h:106
256-bit opaque blob.
Definition: uint256.h:195
static void SipHash_32b(benchmark::Bench &bench)
static void SHA256_STANDARD(benchmark::Bench &bench)
Definition: crypto_hash.cpp:43
static void SHA256_SHANI(benchmark::Bench &bench)
Definition: crypto_hash.cpp:76
static void MuHashPrecompute(benchmark::Bench &bench)
static const uint64_t BUFFER_SIZE
Definition: crypto_hash.cpp:23
BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH)
static void SHA256_32b_AVX2(benchmark::Bench &bench)
static void SHA256D64_1024_SHANI(benchmark::Bench &bench)
static void MuHashFinalize(benchmark::Bench &bench)
static void SHA256_AVX2(benchmark::Bench &bench)
Definition: crypto_hash.cpp:65
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 MuHashMul(benchmark::Bench &bench)
static void SHA256_SSE4(benchmark::Bench &bench)
Definition: crypto_hash.cpp:54
static void BenchRIPEMD160(benchmark::Bench &bench)
Definition: crypto_hash.cpp:25
static void SHA3_256_1M(benchmark::Bench &bench)
Definition: crypto_hash.cpp:87
static void SHA1(benchmark::Bench &bench)
Definition: crypto_hash.cpp:34
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:96
void doNotOptimizeAway(Arg &&arg)
Makes sure none of the given arguments are optimized away by the compiler.
Definition: nanobench.h:1279
@ HIGH
Definition: bench.h:48
void SHA256D64(unsigned char *out, const unsigned char *in, size_t blocks)
Compute multiple double-SHA256's of 64-byte blobs.
Definition: sha256.cpp:749
std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implementation)
Autodetect the best available SHA256 implementation.
Definition: sha256.cpp:585
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172