aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.bench.include1
-rw-r--r--src/bench/addrman.cpp140
2 files changed, 141 insertions, 0 deletions
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
index eae8b1fcd1..766c0fca54 100644
--- a/src/Makefile.bench.include
+++ b/src/Makefile.bench.include
@@ -12,6 +12,7 @@ GENERATED_BENCH_FILES = $(RAW_BENCH_FILES:.raw=.raw.h)
bench_bench_bitcoin_SOURCES = \
$(RAW_BENCH_FILES) \
+ bench/addrman.cpp \
bench/bench_bitcoin.cpp \
bench/bench.cpp \
bench/bench.h \
diff --git a/src/bench/addrman.cpp b/src/bench/addrman.cpp
new file mode 100644
index 0000000000..cc260df2b8
--- /dev/null
+++ b/src/bench/addrman.cpp
@@ -0,0 +1,140 @@
+// 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 <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::State& state)
+{
+ CreateAddresses();
+
+ CAddrMan addrman;
+
+ while (state.KeepRunning()) {
+ AddAddressesToAddrMan(addrman);
+ addrman.Clear();
+ }
+}
+
+static void AddrManSelect(benchmark::State& state)
+{
+ CAddrMan addrman;
+
+ FillAddrMan(addrman);
+
+ while (state.KeepRunning()) {
+ const auto& address = addrman.Select();
+ assert(address.GetPort() > 0);
+ }
+}
+
+static void AddrManGetAddr(benchmark::State& state)
+{
+ CAddrMan addrman;
+
+ FillAddrMan(addrman);
+
+ while (state.KeepRunning()) {
+ const auto& addresses = addrman.GetAddr();
+ assert(addresses.size() > 0);
+ }
+}
+
+static void AddrManGood(benchmark::State& state)
+{
+ /* 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. */
+
+ const uint64_t numLoops = state.m_num_iters * state.m_num_evals;
+
+ std::vector<CAddrMan> addrmans(numLoops);
+ 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;
+ while (state.KeepRunning()) {
+ markSomeAsGood(addrmans.at(i));
+ ++i;
+ }
+}
+
+BENCHMARK(AddrManAdd, 5);
+BENCHMARK(AddrManSelect, 1000000);
+BENCHMARK(AddrManGetAddr, 500);
+BENCHMARK(AddrManGood, 2);