Bitcoin ABC 0.30.5
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/*
15 * A "source" is a source address from which we have received a bunch of other
16 * addresses.
17 */
18
19static constexpr size_t NUM_SOURCES = 64;
20static constexpr size_t NUM_ADDRESSES_PER_SOURCE = 256;
21
22static std::vector<CAddress> g_sources;
23static std::vector<std::vector<CAddress>> g_addresses;
24
25static void CreateAddresses() {
26 // already created
27 if (g_sources.size() > 0) {
28 return;
29 }
30
31 FastRandomContext rng(uint256(std::vector<uint8_t>(32, 123)));
32
33 auto randAddr = [&rng]() {
34 in6_addr addr;
35 memcpy(&addr, rng.randbytes(sizeof(addr)).data(), sizeof(addr));
36
37 uint16_t port;
38 memcpy(&port, rng.randbytes(sizeof(port)).data(), sizeof(port));
39 if (port == 0) {
40 port = 1;
41 }
42
43 CAddress ret(CService(addr, port), NODE_NETWORK);
44
45 ret.nTime = Now<NodeSeconds>();
46
47 return ret;
48 };
49
50 for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
51 g_sources.emplace_back(randAddr());
52 g_addresses.emplace_back();
53 for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
54 g_addresses[source_i].emplace_back(randAddr());
55 }
56 }
57}
58
59static void AddAddressesToAddrMan(AddrMan &addrman) {
60 for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
61 addrman.Add(g_addresses[source_i], g_sources[source_i]);
62 }
63}
64
65static void FillAddrMan(AddrMan &addrman) {
67
68 AddAddressesToAddrMan(addrman);
69}
70
71/* Benchmarks */
72
73static void AddrManAdd(benchmark::Bench &bench) {
75
76 AddrMan addrman(/* asmap= */ std::vector<bool>(),
77 /* consistency_check_ratio= */ 0);
78
79 bench.run([&] {
80 AddAddressesToAddrMan(addrman);
81 addrman.Clear();
82 });
83}
84
85static void AddrManSelect(benchmark::Bench &bench) {
86 AddrMan addrman(/* asmap= */ std::vector<bool>(),
87 /* consistency_check_ratio= */ 0);
88
89 FillAddrMan(addrman);
90
91 bench.run([&] {
92 const auto &address = addrman.Select();
93 assert(address.first.GetPort() > 0);
94 });
95}
96
97static void AddrManGetAddr(benchmark::Bench &bench) {
98 AddrMan addrman(/* asmap= */ std::vector<bool>(),
99 /* consistency_check_ratio= */ 0);
100
101 FillAddrMan(addrman);
102
103 bench.run([&] {
104 const auto &addresses =
105 addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23,
106 /* network */ std::nullopt);
107 assert(addresses.size() > 0);
108 });
109}
110
112 auto markSomeAsGood = [](AddrMan &addrman) {
113 for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
114 for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE;
115 ++addr_i) {
116 addrman.Good(g_addresses[source_i][addr_i]);
117 }
118 }
119 };
120
122
123 bench.run([&] {
124 // To make the benchmark independent of the number of evaluations, we
125 // always prepare a new addrman.
126 // This is necessary because CAddrMan::Good() method modifies the
127 // object, affecting the timing of subsequent calls to the same method
128 // and we want to do the same amount of work in every loop iteration.
129 //
130 // This has some overhead (exactly the result of AddrManAdd benchmark),
131 // but that overhead is constant so improvements in CAddrMan::Good()
132 // will still be noticeable.
133 AddrMan addrman(/*asmap=*/std::vector<bool>(),
134 /*consistency_check_ratio=*/0);
135 AddAddressesToAddrMan(addrman);
136
137 markSomeAsGood(addrman);
138 });
139}
140
static void FillAddrMan(AddrMan &addrman)
Definition: addrman.cpp:65
static void AddrManSelect(benchmark::Bench &bench)
Definition: addrman.cpp:85
static void AddrManAddThenGood(benchmark::Bench &bench)
Definition: addrman.cpp:111
static constexpr size_t NUM_SOURCES
Definition: addrman.cpp:19
BENCHMARK(AddrManAdd)
static std::vector< CAddress > g_sources
Definition: addrman.cpp:22
static void AddrManGetAddr(benchmark::Bench &bench)
Definition: addrman.cpp:97
static constexpr size_t NUM_ADDRESSES_PER_SOURCE
Definition: addrman.cpp:20
static void CreateAddresses()
Definition: addrman.cpp:25
static void AddAddressesToAddrMan(AddrMan &addrman)
Definition: addrman.cpp:59
static void AddrManAdd(benchmark::Bench &bench)
Definition: addrman.cpp:73
static std::vector< std::vector< CAddress > > g_addresses
Definition: addrman.cpp:23
Stochastic address manager.
Definition: addrman.h:68
void Clear()
Definition: addrman.cpp:1363
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:1346
std::pair< CAddress, NodeSeconds > Select(bool newOnly=false) const
Choose an address to connect to.
Definition: addrman.cpp:1342
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
Definition: addrman.cpp:1319
A CService with information about it as peer.
Definition: protocol.h:442
NodeSeconds nTime
Always included in serialization, except in the network format on INIT_PROTO_VERSION.
Definition: protocol.h:544
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:545
Fast randomness source.
Definition: random.h:156
std::vector< uint8_t > randbytes(size_t len)
Generate random bytes.
Definition: random.cpp:690
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:129
@ NODE_NETWORK
Definition: protocol.h:342
assert(!tx.IsCoinBase())