crypto_hash.cpp
1 // Copyright (c) 2016-present 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 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 206 static 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 217 static 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 228 static 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 239 static void MuHashPrecompute(benchmark::Bench& bench) 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 250 static void MuHashFinalize(benchmark::Bench& bench) 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 263 BENCHMARK(BenchRIPEMD160); 264 BENCHMARK(SHA1); 265 BENCHMARK(SHA256_STANDARD); 266 BENCHMARK(SHA256_SSE4); 267 BENCHMARK(SHA256_AVX2); 268 BENCHMARK(SHA256_SHANI); 269 BENCHMARK(SHA512); 270 BENCHMARK(SHA3_256_1M); 271 272 BENCHMARK(SHA256_32b_STANDARD); 273 BENCHMARK(SHA256_32b_SSE4); 274 BENCHMARK(SHA256_32b_AVX2); 275 BENCHMARK(SHA256_32b_SHANI); 276 BENCHMARK(SipHash_32b); 277 BENCHMARK(SHA256D64_1024_STANDARD); 278 BENCHMARK(SHA256D64_1024_SSE4); 279 BENCHMARK(SHA256D64_1024_AVX2); 280 BENCHMARK(SHA256D64_1024_SHANI); 281 282 BENCHMARK(MuHash); 283 BENCHMARK(MuHashMul); 284 BENCHMARK(MuHashDiv); 285 BENCHMARK(MuHashPrecompute); 286 BENCHMARK(MuHashFinalize);