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 <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);