crypto_hash.cpp raw
1 // Copyright (c) 2016-2022 The Limenka 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 auto k0{rng.rand64()}, k1{rng.rand64()};
197 auto val{rng.rand256()};
198 auto i{0U};
199 bench.run([&] {
200 ankerl::nanobench::doNotOptimizeAway(SipHashUint256(k0, k1, val));
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
241 static void MuHashPrecompute(benchmark::Bench& bench)
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
265 BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH);
266 BENCHMARK(SHA1, benchmark::PriorityLevel::HIGH);
267 BENCHMARK(SHA256_STANDARD, benchmark::PriorityLevel::HIGH);
268 BENCHMARK(SHA256_SSE4, benchmark::PriorityLevel::HIGH);
269 BENCHMARK(SHA256_AVX2, benchmark::PriorityLevel::HIGH);
270 BENCHMARK(SHA256_SHANI, benchmark::PriorityLevel::HIGH);
271 BENCHMARK(SHA512, benchmark::PriorityLevel::HIGH);
272 BENCHMARK(SHA3_256_1M, benchmark::PriorityLevel::HIGH);
273
274 BENCHMARK(SHA256_32b_STANDARD, benchmark::PriorityLevel::HIGH);
275 BENCHMARK(SHA256_32b_SSE4, benchmark::PriorityLevel::HIGH);
276 BENCHMARK(SHA256_32b_AVX2, benchmark::PriorityLevel::HIGH);
277 BENCHMARK(SHA256_32b_SHANI, benchmark::PriorityLevel::HIGH);
278 BENCHMARK(SipHash_32b, benchmark::PriorityLevel::HIGH);
279 BENCHMARK(SHA256D64_1024_STANDARD, benchmark::PriorityLevel::HIGH);
280 BENCHMARK(SHA256D64_1024_SSE4, benchmark::PriorityLevel::HIGH);
281 BENCHMARK(SHA256D64_1024_AVX2, benchmark::PriorityLevel::HIGH);
282 BENCHMARK(SHA256D64_1024_SHANI, benchmark::PriorityLevel::HIGH);
283
284 BENCHMARK(MuHash, benchmark::PriorityLevel::HIGH);
285 BENCHMARK(MuHashMul, benchmark::PriorityLevel::HIGH);
286 BENCHMARK(MuHashDiv, benchmark::PriorityLevel::HIGH);
287 BENCHMARK(MuHashPrecompute, benchmark::PriorityLevel::HIGH);
288 BENCHMARK(MuHashFinalize, benchmark::PriorityLevel::HIGH);
289