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 2 : 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