Was wondering where most time is spent here, a quick profiling on master reveals:
<img width="600" alt="image" src="https://github.com/user-attachments/assets/0d7d6c4f-b4bc-482a-9760-1660a6659e35">
i.e. serialization seems to take most time - not sure there's anything we can do about that here.
But checked how much time is spent reallocating the vector instead, i.e.:
static void AddrManAdd2(benchmark::Bench& bench)
{
bench.run([&] {
AddrMan addr_man{EMPTY_NETGROUPMAN, /*deterministic=*/true, ADDRMAN_CONSISTENCY_CHECK_RATIO};
// Add one address to the new table
CService addr = Lookup("250.3.1.1", 8333, false).value();
addr_man.Add({CAddress(addr, NODE_NONE)}, addr, std::chrono::seconds{1234});
std::vector<CAddress> addresses;
// addresses.reserve(10000);
for(int i = 0; i < 10000; ++i) {
addresses.emplace_back(addr, NODE_NONE);
}
addr_man.Add(addresses, addr, std::chrono::seconds{1234});
ankerl::nanobench::doNotOptimizeAway(addr_man.Size());
});
}
which reveals a small, but measurable gain if we add a reserve to vector:
| ns/op | op/s | err% | total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
| 1,116,935.10 | 895.31 | 2.8% | 0.37 | AddrManAdd2
vs
std::vector<CAddress> addresses;
addresses.reserve(10000);
| ns/op | op/s | err% | total | benchmark
|--------------------:|--------------------:|--------:|----------:|:----------
| 971,714.29 | 1,029.11 | 0.5% | 0.35 | AddrManAdd2
note: push_back vs emplace_back doesn't seem to make a difference here.