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 <bench/bench.h>
6 #include <net.h>
7 #include <netaddress.h>
8 #include <random.h>
9 #include <test/util/net.h>
10 #include <test/util/setup_common.h>
11 
12 #include <algorithm>
13 #include <functional>
14 #include <vector>
15 
EvictionProtectionCommon(benchmark::Bench & bench,int num_candidates,std::function<void (NodeEvictionCandidate &)> candidate_setup_fn)16 static void EvictionProtectionCommon(
17     benchmark::Bench& bench,
18     int num_candidates,
19     std::function<void(NodeEvictionCandidate&)> candidate_setup_fn)
20 {
21     using Candidates = std::vector<NodeEvictionCandidate>;
22     FastRandomContext random_context{true};
23     bench.warmup(100).epochIterations(1100);
24 
25     Candidates candidates{GetRandomNodeEvictionCandidates(num_candidates, random_context)};
26     for (auto& c : candidates) {
27         candidate_setup_fn(c);
28     }
29 
30     std::vector<Candidates> copies{
31         static_cast<size_t>(bench.epochs() * bench.epochIterations()), candidates};
32     size_t i{0};
33     bench.run([&] {
34         ProtectEvictionCandidatesByRatio(copies.at(i));
35         ++i;
36     });
37 }
38 
39 /* Benchmarks */
40 
EvictionProtection0Networks250Candidates(benchmark::Bench & bench)41 static void EvictionProtection0Networks250Candidates(benchmark::Bench& bench)
42 {
43     EvictionProtectionCommon(
44         bench,
45         250 /* num_candidates */,
46         [](NodeEvictionCandidate& c) {
47             c.nTimeConnected = c.id;
48             c.m_network = NET_IPV4;
49         });
50 }
51 
EvictionProtection1Networks250Candidates(benchmark::Bench & bench)52 static void EvictionProtection1Networks250Candidates(benchmark::Bench& bench)
53 {
54     EvictionProtectionCommon(
55         bench,
56         250 /* num_candidates */,
57         [](NodeEvictionCandidate& c) {
58             c.nTimeConnected = c.id;
59             c.m_is_local = false;
60             if (c.id >= 130 && c.id < 240) { // 110 Tor
61                 c.m_network = NET_ONION;
62             } else {
63                 c.m_network = NET_IPV4;
64             }
65         });
66 }
67 
EvictionProtection2Networks250Candidates(benchmark::Bench & bench)68 static void EvictionProtection2Networks250Candidates(benchmark::Bench& bench)
69 {
70     EvictionProtectionCommon(
71         bench,
72         250 /* num_candidates */,
73         [](NodeEvictionCandidate& c) {
74             c.nTimeConnected = c.id;
75             c.m_is_local = false;
76             if (c.id >= 90 && c.id < 160) { // 70 Tor
77                 c.m_network = NET_ONION;
78             } else if (c.id >= 170 && c.id < 250) { // 80 I2P
79                 c.m_network = NET_I2P;
80             } else {
81                 c.m_network = NET_IPV4;
82             }
83         });
84 }
85 
EvictionProtection3Networks050Candidates(benchmark::Bench & bench)86 static void EvictionProtection3Networks050Candidates(benchmark::Bench& bench)
87 {
88     EvictionProtectionCommon(
89         bench,
90         50 /* num_candidates */,
91         [](NodeEvictionCandidate& c) {
92             c.nTimeConnected = c.id;
93             c.m_is_local = (c.id == 28 || c.id == 47); //  2 localhost
94             if (c.id >= 30 && c.id < 47) {             // 17 I2P
95                 c.m_network = NET_I2P;
96             } else if (c.id >= 24 && c.id < 28) { //  4 Tor
97                 c.m_network = NET_ONION;
98             } else {
99                 c.m_network = NET_IPV4;
100             }
101         });
102 }
103 
EvictionProtection3Networks100Candidates(benchmark::Bench & bench)104 static void EvictionProtection3Networks100Candidates(benchmark::Bench& bench)
105 {
106     EvictionProtectionCommon(
107         bench,
108         100 /* num_candidates */,
109         [](NodeEvictionCandidate& c) {
110             c.nTimeConnected = c.id;
111             c.m_is_local = (c.id >= 55 && c.id < 60); //  5 localhost
112             if (c.id >= 70 && c.id < 80) {            // 10 I2P
113                 c.m_network = NET_I2P;
114             } else if (c.id >= 80 && c.id < 96) { // 16 Tor
115                 c.m_network = NET_ONION;
116             } else {
117                 c.m_network = NET_IPV4;
118             }
119         });
120 }
121 
EvictionProtection3Networks250Candidates(benchmark::Bench & bench)122 static void EvictionProtection3Networks250Candidates(benchmark::Bench& bench)
123 {
124     EvictionProtectionCommon(
125         bench,
126         250 /* num_candidates */,
127         [](NodeEvictionCandidate& c) {
128             c.nTimeConnected = c.id;
129             c.m_is_local = (c.id >= 140 && c.id < 160); // 20 localhost
130             if (c.id >= 170 && c.id < 180) {            // 10 I2P
131                 c.m_network = NET_I2P;
132             } else if (c.id >= 190 && c.id < 240) { // 50 Tor
133                 c.m_network = NET_ONION;
134             } else {
135                 c.m_network = NET_IPV4;
136             }
137         });
138 }
139 
140 // Candidate numbers used for the benchmarks:
141 // -  50 candidates simulates a possible use of -maxconnections
142 // - 100 candidates approximates an average node with default settings
143 // - 250 candidates is the number of peers reported by operators of busy nodes
144 
145 // No disadvantaged networks, with 250 eviction candidates.
146 BENCHMARK(EvictionProtection0Networks250Candidates);
147 
148 // 1 disadvantaged network (Tor) with 250 eviction candidates.
149 BENCHMARK(EvictionProtection1Networks250Candidates);
150 
151 // 2 disadvantaged networks (I2P, Tor) with 250 eviction candidates.
152 BENCHMARK(EvictionProtection2Networks250Candidates);
153 
154 // 3 disadvantaged networks (I2P/localhost/Tor) with 50/100/250 eviction candidates.
155 BENCHMARK(EvictionProtection3Networks050Candidates);
156 BENCHMARK(EvictionProtection3Networks100Candidates);
157 BENCHMARK(EvictionProtection3Networks250Candidates);
158