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 : 1 : uint32_t FindBestImplementation()
25 : : {
26 : 1 : std::optional<std::pair<SteadyClock::duration, uint32_t>> best;
27 : :
28 : 1 : uint32_t max_impl = Minisketch::MaxImplementation();
29 [ + + ]: 4 : for (uint32_t impl = 0; impl <= max_impl; ++impl) {
30 : 3 : std::vector<SteadyClock::duration> benches;
31 : 3 : uint64_t offset = 0;
32 : : /* Run a little benchmark with capacity 32, adding 184 entries, and decoding 11 of them once. */
33 [ + + ]: 25 : for (int b = 0; b < 11; ++b) {
34 [ + + ]: 23 : if (!Minisketch::ImplementationSupported(BITS, impl)) break;
35 : 22 : Minisketch sketch(BITS, impl, 32);
36 : 22 : auto start = SteadyClock::now();
37 [ + + ]: 2222 : for (uint64_t e = 0; e < 100; ++e) {
38 : 2200 : sketch.Add(e*1337 + b*13337 + offset);
39 : : }
40 [ + + ]: 1870 : for (uint64_t e = 0; e < 84; ++e) {
41 : 1848 : sketch.Add(e*1337 + b*13337 + offset);
42 : : }
43 [ + - ]: 22 : offset += (*sketch.Decode(32))[0];
44 : 22 : auto stop = SteadyClock::now();
45 [ + - + - ]: 22 : benches.push_back(stop - start);
46 : 22 : }
47 : : /* Remember which implementation has the best median benchmark time. */
48 [ + + ]: 3 : if (!benches.empty()) {
49 : 2 : std::sort(benches.begin(), benches.end());
50 [ + + + - ]: 2 : if (!best || best->first > benches[5]) {
51 [ + + ]: 5 : best = std::make_pair(benches[5], impl);
52 : : }
53 : : }
54 : 3 : }
55 [ - + ]: 1 : assert(best.has_value());
56 : 1 : LogPrintf("Using Minisketch implementation number %i\n", best->second);
57 : 1 : return best->second;
58 : : }
59 : :
60 : 400 : uint32_t Minisketch32Implementation()
61 : : {
62 : : // Fast compute-once idiom.
63 [ + + + - : 400 : static uint32_t best = FindBestImplementation();
+ - ]
64 : 400 : return best;
65 : : }
66 : :
67 : : } // namespace
68 : :
69 : :
70 : 400 : Minisketch MakeMinisketch32(size_t capacity)
71 : : {
72 : 400 : 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
|