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 <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 }); 48 SHA256AutoDetect(); 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 }); 59 SHA256AutoDetect(); 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 }); 70 SHA256AutoDetect(); 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 }); 81 SHA256AutoDetect(); 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 93 static void SHA256_32b_STANDARD(benchmark::Bench& bench) 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 }); 102 SHA256AutoDetect(); 103 } 104 105 static void SHA256_32b_SSE4(benchmark::Bench& bench) 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 }); 114 SHA256AutoDetect(); 115 } 116 117 static void SHA256_32b_AVX2(benchmark::Bench& bench) 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 }); 126 SHA256AutoDetect(); 127 } 128 129 static void SHA256_32b_SHANI(benchmark::Bench& bench) 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 }); 138 SHA256AutoDetect(); 139 } 140 141 static void SHA256D64_1024_STANDARD(benchmark::Bench& bench) 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 }); 148 SHA256AutoDetect(); 149 } 150 151 static void SHA256D64_1024_SSE4(benchmark::Bench& bench) 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 }); 158 SHA256AutoDetect(); 159 } 160 161 static void SHA256D64_1024_AVX2(benchmark::Bench& bench) 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 }); 168 SHA256AutoDetect(); 169 } 170 171 static void SHA256D64_1024_SHANI(benchmark::Bench& bench) 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 }); 178 SHA256AutoDetect(); 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 199 static void FastRandom_32bit(benchmark::Bench& bench) 200 { 201 FastRandomContext rng(true); 202 bench.run([&] { 203 rng.rand32(); 204 }); 205 } 206 207 static void FastRandom_1bit(benchmark::Bench& bench) 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 248 static void MuHashPrecompute(benchmark::Bench& bench) 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 259 BENCHMARK(BenchRIPEMD160, benchmark::PriorityLevel::HIGH); 260 BENCHMARK(SHA1, benchmark::PriorityLevel::HIGH); 261 BENCHMARK(SHA256_STANDARD, benchmark::PriorityLevel::HIGH); 262 BENCHMARK(SHA256_SSE4, benchmark::PriorityLevel::HIGH); 263 BENCHMARK(SHA256_AVX2, benchmark::PriorityLevel::HIGH); 264 BENCHMARK(SHA256_SHANI, benchmark::PriorityLevel::HIGH); 265 BENCHMARK(SHA512, benchmark::PriorityLevel::HIGH); 266 BENCHMARK(SHA3_256_1M, benchmark::PriorityLevel::HIGH); 267 268 BENCHMARK(SHA256_32b_STANDARD, benchmark::PriorityLevel::HIGH); 269 BENCHMARK(SHA256_32b_SSE4, benchmark::PriorityLevel::HIGH); 270 BENCHMARK(SHA256_32b_AVX2, benchmark::PriorityLevel::HIGH); 271 BENCHMARK(SHA256_32b_SHANI, benchmark::PriorityLevel::HIGH); 272 BENCHMARK(SipHash_32b, benchmark::PriorityLevel::HIGH); 273 BENCHMARK(SHA256D64_1024_STANDARD, benchmark::PriorityLevel::HIGH); 274 BENCHMARK(SHA256D64_1024_SSE4, benchmark::PriorityLevel::HIGH); 275 BENCHMARK(SHA256D64_1024_AVX2, benchmark::PriorityLevel::HIGH); 276 BENCHMARK(SHA256D64_1024_SHANI, benchmark::PriorityLevel::HIGH); 277 BENCHMARK(FastRandom_32bit, benchmark::PriorityLevel::HIGH); 278 BENCHMARK(FastRandom_1bit, benchmark::PriorityLevel::HIGH); 279 280 BENCHMARK(MuHash, benchmark::PriorityLevel::HIGH); 281 BENCHMARK(MuHashMul, benchmark::PriorityLevel::HIGH); 282 BENCHMARK(MuHashDiv, benchmark::PriorityLevel::HIGH); 283 BENCHMARK(MuHashPrecompute, benchmark::PriorityLevel::HIGH);