Branch data Line data Source code
1 : : // Copyright (c) 2021 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 : : #include <node/minisketchwrapper.h> 6 : : 7 : : #include <logging.h> 8 : : #include <util/time.h> 9 : : 10 : : #include <minisketch.h> 11 : : 12 : : #include <algorithm> 13 : : #include <cstddef> 14 : : #include <cstdint> 15 : : #include <optional> 16 : : #include <utility> 17 : : #include <vector> 18 : : 19 : : namespace node { 20 : : namespace { 21 : : 22 : : static constexpr uint32_t BITS = 32; 23 : : 24 : 0 : uint32_t FindBestImplementation() 25 : : { 26 : 0 : std::optional<std::pair<SteadyClock::duration, uint32_t>> best; 27 : : 28 : 0 : uint32_t max_impl = Minisketch::MaxImplementation(); 29 [ # # ]: 0 : for (uint32_t impl = 0; impl <= max_impl; ++impl) { 30 : 0 : std::vector<SteadyClock::duration> benches; 31 : 0 : uint64_t offset = 0; 32 : : /* Run a little benchmark with capacity 32, adding 184 entries, and decoding 11 of them once. */ 33 [ # # ]: 0 : for (int b = 0; b < 11; ++b) { 34 [ # # ]: 0 : if (!Minisketch::ImplementationSupported(BITS, impl)) break; 35 : 0 : Minisketch sketch(BITS, impl, 32); 36 : 0 : auto start = SteadyClock::now(); 37 [ # # ]: 0 : for (uint64_t e = 0; e < 100; ++e) { 38 : 0 : sketch.Add(e*1337 + b*13337 + offset); 39 : 0 : } 40 [ # # ]: 0 : for (uint64_t e = 0; e < 84; ++e) { 41 : 0 : sketch.Add(e*1337 + b*13337 + offset); 42 : 0 : } 43 [ # # ]: 0 : offset += (*sketch.Decode(32))[0]; 44 : 0 : auto stop = SteadyClock::now(); 45 [ # # ][ # # ]: 0 : benches.push_back(stop - start); 46 : 0 : } 47 : : /* Remember which implementation has the best median benchmark time. */ 48 [ # # ]: 0 : if (!benches.empty()) { 49 [ # # ]: 0 : std::sort(benches.begin(), benches.end()); 50 [ # # ][ # # ]: 0 : if (!best || best->first > benches[5]) { [ # # ] 51 [ # # ]: 0 : best = std::make_pair(benches[5], impl); 52 : 0 : } 53 : 0 : } 54 : 0 : } 55 [ # # ]: 0 : assert(best.has_value()); 56 [ # # ][ # # ]: 0 : LogPrintf("Using Minisketch implementation number %i\n", best->second); [ # # ] 57 : 0 : return best->second; 58 : 0 : } 59 : : 60 : 0 : uint32_t Minisketch32Implementation() 61 : : { 62 : : // Fast compute-once idiom. 63 [ # # ][ # # ]: 0 : static uint32_t best = FindBestImplementation(); [ # # ] 64 : 0 : return best; 65 : 0 : } 66 : : 67 : : } // namespace 68 : : 69 : : 70 : 0 : Minisketch MakeMinisketch32(size_t capacity) 71 : : { 72 : 0 : return Minisketch(BITS, Minisketch32Implementation(), capacity); 73 : : } 74 : : 75 : 0 : Minisketch MakeMinisketch32FP(size_t max_elements, uint32_t fpbits) 76 : : { 77 : 0 : return Minisketch::CreateFP(BITS, Minisketch32Implementation(), max_elements, fpbits); 78 : : } 79 : : } // namespace node