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
16static constexpr size_t NUM_SOURCES = 64;
17static constexpr size_t NUM_ADDRESSES_PER_SOURCE = 256;
18
19static std::vector<CAddress> g_sources;
20static std::vector<std::vector<CAddress>> g_addresses;
21
22static 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
56static void AddAddressesToAddrMan(AddrMan& 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
63static void FillAddrMan(AddrMan& addrman)
64{
66
67 AddAddressesToAddrMan(addrman);
68}
69
70/* Benchmarks */
71
72static void AddrManAdd(benchmark::Bench& bench)
73{
75
76 bench.run([&] {
77 AddrMan addrman{/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0};
78 AddAddressesToAddrMan(addrman);
79 });
80}
81
83{
84 AddrMan 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.first.GetPort() > 0);
91 });
92}
93
95{
96 AddrMan 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
107{
108 auto markSomeAsGood = [](AddrMan& addrman) {
109 for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
110 for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
111 addrman.Good(g_addresses[source_i][addr_i]);
112 }
113 }
114 };
115
117
118 bench.run([&] {
119 // To make the benchmark independent of the number of evaluations, we always prepare a new addrman.
120 // This is necessary because AddrMan::Good() method modifies the object, affecting the timing of subsequent calls
121 // to the same method and we want to do the same amount of work in every loop iteration.
122 //
123 // This has some overhead (exactly the result of AddrManAdd benchmark), but that overhead is constant so improvements in
124 // AddrMan::Good() will still be noticeable.
125 AddrMan addrman(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 0);
126 AddAddressesToAddrMan(addrman);
127
128 markSomeAsGood(addrman);
129 });
130}
131
static void FillAddrMan(AddrMan &addrman)
Definition: addrman.cpp:63
static void AddrManSelect(benchmark::Bench &bench)
Definition: addrman.cpp:82
static void AddrManAddThenGood(benchmark::Bench &bench)
Definition: addrman.cpp:106
static constexpr size_t NUM_SOURCES
Definition: addrman.cpp:16
BENCHMARK(AddrManAdd)
static std::vector< CAddress > g_sources
Definition: addrman.cpp:19
static void AddrManGetAddr(benchmark::Bench &bench)
Definition: addrman.cpp:94
static constexpr size_t NUM_ADDRESSES_PER_SOURCE
Definition: addrman.cpp:17
static void CreateAddresses()
Definition: addrman.cpp:22
static void AddAddressesToAddrMan(AddrMan &addrman)
Definition: addrman.cpp:56
static void AddrManAdd(benchmark::Bench &bench)
Definition: addrman.cpp:72
static std::vector< std::vector< CAddress > > g_addresses
Definition: addrman.cpp:20
Stochastic address manager.
Definition: addrman.h:55
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
Definition: addrman.cpp:1183
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Attempt to add one or more addresses to addrman's new table.
Definition: addrman.cpp:1153
std::pair< CAddress, int64_t > Select(bool newOnly=false) const
Choose an address to connect to.
Definition: addrman.cpp:1178
A CService with information about it as peer.
Definition: protocol.h:359
uint32_t nTime
Always included in serialization.
Definition: protocol.h:440
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:523
Fast randomness source.
Definition: random.h:120
std::vector< unsigned char > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:626
Main entry point to nanobench's benchmarking facility.
Definition: nanobench.h:616
Bench & run(char const *benchmarkName, Op &&op)
Repeatedly calls op() based on the configuration, and performs measurements.
Definition: nanobench.h:1183
256-bit opaque blob.
Definition: uint256.h:124
@ NODE_NETWORK
Definition: protocol.h:277
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
assert(!tx.IsCoinBase())