Bitcoin Core  22.99.0
P2P Digital Currency
addrman.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020-2020 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 <addrman.h>
6 #include <bench/bench.h>
7 #include <random.h>
8 #include <util/check.h>
9 #include <util/time.h>
10 
11 #include <optional>
12 #include <vector>
13 
14 /* A "source" is a source address from which we have received a bunch of other addresses. */
15 
16 static constexpr size_t NUM_SOURCES = 64;
17 static constexpr size_t NUM_ADDRESSES_PER_SOURCE = 256;
18 
19 static std::vector<CAddress> g_sources;
20 static std::vector<std::vector<CAddress>> g_addresses;
21 
22 static void CreateAddresses()
23 {
24  if (g_sources.size() > 0) { // already created
25  return;
26  }
27 
28  FastRandomContext rng(uint256(std::vector<unsigned char>(32, 123)));
29 
30  auto randAddr = [&rng]() {
31  in6_addr addr;
32  memcpy(&addr, rng.randbytes(sizeof(addr)).data(), sizeof(addr));
33 
34  uint16_t port;
35  memcpy(&port, rng.randbytes(sizeof(port)).data(), sizeof(port));
36  if (port == 0) {
37  port = 1;
38  }
39 
40  CAddress ret(CService(addr, port), NODE_NETWORK);
41 
42  ret.nTime = GetAdjustedTime();
43 
44  return ret;
45  };
46 
47  for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
48  g_sources.emplace_back(randAddr());
49  g_addresses.emplace_back();
50  for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
51  g_addresses[source_i].emplace_back(randAddr());
52  }
53  }
54 }
55 
56 static void AddAddressesToAddrMan(CAddrMan& addrman)
57 {
58  for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
59  addrman.Add(g_addresses[source_i], g_sources[source_i]);
60  }
61 }
62 
63 static void FillAddrMan(CAddrMan& addrman)
64 {
66 
67  AddAddressesToAddrMan(addrman);
68 }
69 
70 /* Benchmarks */
71 
72 static void AddrManAdd(benchmark::Bench& bench)
73 {
75 
76  bench.run([&] {
77  CAddrMan addrman{/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0};
78  AddAddressesToAddrMan(addrman);
79  });
80 }
81 
82 static void AddrManSelect(benchmark::Bench& bench)
83 {
84  CAddrMan addrman(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0);
85 
86  FillAddrMan(addrman);
87 
88  bench.run([&] {
89  const auto& address = addrman.Select();
90  assert(address.GetPort() > 0);
91  });
92 }
93 
94 static void AddrManGetAddr(benchmark::Bench& bench)
95 {
96  CAddrMan addrman(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0);
97 
98  FillAddrMan(addrman);
99 
100  bench.run([&] {
101  const auto& addresses = addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ std::nullopt);
102  assert(addresses.size() > 0);
103  });
104 }
105 
106 static void AddrManGood(benchmark::Bench& bench)
107 {
108  /* Create many CAddrMan objects - one to be modified at each loop iteration.
109  * This is necessary because the CAddrMan::Good() method modifies the
110  * object, affecting the timing of subsequent calls to the same method and
111  * we want to do the same amount of work in every loop iteration. */
112 
113  bench.epochs(5).epochIterations(1);
114  const uint64_t addrman_count{bench.epochs() * bench.epochIterations()};
115  Assert(addrman_count == 5U);
116 
117  std::vector<std::unique_ptr<CAddrMan>> addrmans(addrman_count);
118  for (size_t i{0}; i < addrman_count; ++i) {
119  addrmans[i] = std::make_unique<CAddrMan>(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0);
120  FillAddrMan(*addrmans[i]);
121  }
122 
123  auto markSomeAsGood = [](CAddrMan& addrman) {
124  for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
125  for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
126  if (addr_i % 32 == 0) {
127  addrman.Good(g_addresses[source_i][addr_i]);
128  }
129  }
130  }
131  };
132 
133  uint64_t i = 0;
134  bench.run([&] {
135  markSomeAsGood(*addrmans.at(i));
136  ++i;
137  });
138 }
139 
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:539
assert
assert(!tx.IsCoinBase())
check.h
NUM_SOURCES
static constexpr size_t NUM_SOURCES
Definition: addrman.cpp:16
ankerl::nanobench::Bench::epochIterations
Bench & epochIterations(uint64_t numIters) noexcept
Sets exactly the number of iterations for each epoch.
CAddrMan::Select
CAddrInfo Select(bool newOnly=false) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Choose an address to connect to.
Definition: addrman.h:226
AddrManAdd
static void AddrManAdd(benchmark::Bench &bench)
Definition: addrman.cpp:72
FastRandomContext::randbytes
std::vector< unsigned char > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:626
ankerl::nanobench::Bench
Main entry point to nanobench's benchmarking facility.
Definition: nanobench.h:614
CAddrMan::GetAddr
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return all or many randomly selected addresses, optionally by network.
Definition: addrman.h:243
NODE_NETWORK
@ NODE_NETWORK
Definition: protocol.h:277
g_sources
static std::vector< CAddress > g_sources
Definition: addrman.cpp:19
CAddress::nTime
uint32_t nTime
Always included in serialization.
Definition: protocol.h:440
NUM_ADDRESSES_PER_SOURCE
static constexpr size_t NUM_ADDRESSES_PER_SOURCE
Definition: addrman.cpp:17
Assert
#define Assert(val)
Identity function.
Definition: check.h:57
random.h
FillAddrMan
static void FillAddrMan(CAddrMan &addrman)
Definition: addrman.cpp:63
AddAddressesToAddrMan
static void AddAddressesToAddrMan(CAddrMan &addrman)
Definition: addrman.cpp:56
ankerl::nanobench::Bench::run
Bench & run(char const *benchmarkName, Op &&op)
Repeatedly calls op() based on the configuration, and performs measurements.
Definition: nanobench.h:1181
time.h
CAddrMan::Add
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Add addresses to addrman's new table.
Definition: addrman.h:167
uint256
256-bit opaque blob.
Definition: uint256.h:124
bench.h
g_addresses
static std::vector< std::vector< CAddress > > g_addresses
Definition: addrman.cpp:20
AddrManGetAddr
static void AddrManGetAddr(benchmark::Bench &bench)
Definition: addrman.cpp:94
CAddrMan
Stochastical (IP) address manager.
Definition: addrman.h:142
BENCHMARK
BENCHMARK(AddrManAdd)
GetAdjustedTime
int64_t GetAdjustedTime()
Definition: timedata.cpp:34
CAddress
A CService with information about it as peer.
Definition: protocol.h:358
ankerl::nanobench::Bench::epochs
Bench & epochs(size_t numEpochs) noexcept
Controls number of epochs, the number of measurements to perform.
addrman.h
CreateAddresses
static void CreateAddresses()
Definition: addrman.cpp:22
AddrManSelect
static void AddrManSelect(benchmark::Bench &bench)
Definition: addrman.cpp:82
AddrManGood
static void AddrManGood(benchmark::Bench &bench)
Definition: addrman.cpp:106
FastRandomContext
Fast randomness source.
Definition: random.h:119