dash/src/bench/addrman.cpp
Kittywhiskers Van Gogh cf27db8574 partial bitcoin#21843: enable GetAddr, GetAddresses, and getnodeaddresses by network
excludes:
- 6c98c099918bd20e2d3aa123643d6e3594e080e4
- 3f89c0e9902338ad8a507a938dceeeb3191eece6
- ce6bca88e8c685c69686e0b8dc095ffc3e2ac34d
2023-07-24 20:45:49 +03:00

142 lines
3.6 KiB
C++

// Copyright (c) 2020-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <addrman.h>
#include <bench/bench.h>
#include <random.h>
#include <util/time.h>
#include <optional>
#include <vector>
/* A "source" is a source address from which we have received a bunch of other addresses. */
static constexpr size_t NUM_SOURCES = 64;
static constexpr size_t NUM_ADDRESSES_PER_SOURCE = 256;
static std::vector<CAddress> g_sources;
static std::vector<std::vector<CAddress>> g_addresses;
static void CreateAddresses()
{
if (g_sources.size() > 0) { // already created
return;
}
FastRandomContext rng(uint256(std::vector<unsigned char>(32, 123)));
auto randAddr = [&rng]() {
in6_addr addr;
memcpy(&addr, rng.randbytes(sizeof(addr)).data(), sizeof(addr));
uint16_t port;
memcpy(&port, rng.randbytes(sizeof(port)).data(), sizeof(port));
if (port == 0) {
port = 1;
}
CAddress ret(CService(addr, port), NODE_NETWORK);
ret.nTime = GetAdjustedTime();
return ret;
};
for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
g_sources.emplace_back(randAddr());
g_addresses.emplace_back();
for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
g_addresses[source_i].emplace_back(randAddr());
}
}
}
static void AddAddressesToAddrMan(CAddrMan& addrman)
{
for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
addrman.Add(g_addresses[source_i], g_sources[source_i]);
}
}
static void FillAddrMan(CAddrMan& addrman)
{
CreateAddresses();
AddAddressesToAddrMan(addrman);
}
/* Benchmarks */
static void AddrManAdd(benchmark::Bench& bench)
{
CreateAddresses();
CAddrMan addrman;
bench.run([&] {
AddAddressesToAddrMan(addrman);
addrman.Clear();
});
}
static void AddrManSelect(benchmark::Bench& bench)
{
CAddrMan addrman;
FillAddrMan(addrman);
bench.run([&] {
const auto& address = addrman.Select();
assert(address.GetPort() > 0);
});
}
static void AddrManGetAddr(benchmark::Bench& bench)
{
CAddrMan addrman;
FillAddrMan(addrman);
bench.run([&] {
const auto& addresses = addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ std::nullopt);
assert(addresses.size() > 0);
});
}
static void AddrManGood(benchmark::Bench& bench)
{
/* Create many CAddrMan objects - one to be modified at each loop iteration.
* This is necessary because the CAddrMan::Good() method modifies the
* object, affecting the timing of subsequent calls to the same method and
* we want to do the same amount of work in every loop iteration. */
bench.epochs(5).epochIterations(1);
std::vector<CAddrMan> addrmans(bench.epochs() * bench.epochIterations());
for (auto& addrman : addrmans) {
FillAddrMan(addrman);
}
auto markSomeAsGood = [](CAddrMan& addrman) {
for (size_t source_i = 0; source_i < NUM_SOURCES; ++source_i) {
for (size_t addr_i = 0; addr_i < NUM_ADDRESSES_PER_SOURCE; ++addr_i) {
if (addr_i % 32 == 0) {
addrman.Good(g_addresses[source_i][addr_i]);
}
}
}
};
uint64_t i = 0;
bench.run([&] {
markSomeAsGood(addrmans.at(i));
++i;
});
}
BENCHMARK(AddrManAdd);
BENCHMARK(AddrManSelect);
BENCHMARK(AddrManGetAddr);
BENCHMARK(AddrManGood);