From 6924d54954184d619e768802e48f040a8a15c01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Wo=CC=81jcik?= <3044353+pwojcikdev@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:24:19 +0100 Subject: [PATCH] Evict fully synced accounts from priority set faster --- nano/node/bootstrap/account_sets.cpp | 10 +++++-- nano/node/bootstrap/account_sets.hpp | 9 +++++- nano/node/bootstrap/bootstrap_service.cpp | 34 +++++++++++++++-------- nano/node/bootstrap/bootstrap_service.hpp | 7 +++-- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/nano/node/bootstrap/account_sets.cpp b/nano/node/bootstrap/account_sets.cpp index d73d314ae0..421ffddb46 100644 --- a/nano/node/bootstrap/account_sets.cpp +++ b/nano/node/bootstrap/account_sets.cpp @@ -220,7 +220,7 @@ void nano::bootstrap::account_sets::trim_overflow () } } -nano::account nano::bootstrap::account_sets::next_priority (std::function const & filter) +auto nano::bootstrap::account_sets::next_priority (std::function const & filter) -> priority_result { if (priorities.empty ()) { @@ -239,10 +239,14 @@ nano::account nano::bootstrap::account_sets::next_priority (std::function const & filter) diff --git a/nano/node/bootstrap/account_sets.hpp b/nano/node/bootstrap/account_sets.hpp index 8456efa3d8..59bdbf95af 100644 --- a/nano/node/bootstrap/account_sets.hpp +++ b/nano/node/bootstrap/account_sets.hpp @@ -63,10 +63,17 @@ namespace bootstrap */ void sync_dependencies (); + struct priority_result + { + nano::account account; + double priority; + unsigned fails; + }; + /** * Sampling */ - nano::account next_priority (std::function const & filter); + priority_result next_priority (std::function const & filter); nano::block_hash next_blocking (std::function const & filter); bool blocked (nano::account const & account) const; diff --git a/nano/node/bootstrap/bootstrap_service.cpp b/nano/node/bootstrap/bootstrap_service.cpp index 58ccaa3c7e..c2d8188249 100644 --- a/nano/node/bootstrap/bootstrap_service.cpp +++ b/nano/node/bootstrap/bootstrap_service.cpp @@ -372,30 +372,28 @@ size_t nano::bootstrap_service::count_tags (nano::block_hash const & hash, query return std::count_if (begin, end, [source] (auto const & tag) { return tag.source == source; }); } -std::pair nano::bootstrap_service::next_priority () +nano::bootstrap::account_sets::priority_result nano::bootstrap_service::next_priority () { debug_assert (!mutex.try_lock ()); - auto account = accounts.next_priority ([this] (nano::account const & account) { + auto next = accounts.next_priority ([this] (nano::account const & account) { return count_tags (account, query_source::priority) < 4; }); - if (account.is_zero ()) + if (next.account.is_zero ()) { return {}; } stats.inc (nano::stat::type::bootstrap_next, nano::stat::detail::next_priority); - accounts.timestamp_set (account); - // TODO: Priority could be returned by the accounts.next_priority() call - return { account, accounts.priority (account) }; + return next; } -std::pair nano::bootstrap_service::wait_priority () +nano::bootstrap::account_sets::priority_result nano::bootstrap_service::wait_priority () { - std::pair result{ 0, 0 }; + nano::bootstrap::account_sets::priority_result result{}; wait ([this, &result] () { debug_assert (!mutex.try_lock ()); result = next_priority (); - if (!result.first.is_zero ()) + if (!result.account.is_zero ()) { return true; } @@ -565,14 +563,26 @@ void nano::bootstrap_service::run_one_priority () { return; } - auto [account, priority] = wait_priority (); + auto [account, priority, fails] = wait_priority (); if (account.is_zero ()) { return; } + + // Decide how many blocks to request size_t const min_pull_count = 2; - auto count = std::clamp (static_cast (priority), min_pull_count, nano::bootstrap_server::max_blocks); - request (account, count, channel, query_source::priority); + auto pull_count = std::clamp (static_cast (priority), min_pull_count, nano::bootstrap_server::max_blocks); + + bool sent = request (account, pull_count, channel, query_source::priority); + + // Only cooldown accounts that are likely to have more blocks + // This is to avoid requesting blocks from the same frontier multiple times, before the block processor had a chance to process them + // Not throttling accounts that are probably up-to-date allows us to evict them from the priority set faster + if (sent && fails == 0) + { + nano::lock_guard lock{ mutex }; + accounts.timestamp_set (account); + } } void nano::bootstrap_service::run_priorities () diff --git a/nano/node/bootstrap/bootstrap_service.hpp b/nano/node/bootstrap/bootstrap_service.hpp index d77b048d44..7e881e5c9d 100644 --- a/nano/node/bootstrap/bootstrap_service.hpp +++ b/nano/node/bootstrap/bootstrap_service.hpp @@ -117,9 +117,10 @@ class bootstrap_service void wait_blockprocessor () const; /* Waits for a channel that is not full */ std::shared_ptr wait_channel (); - /* Waits until a suitable account outside of cool down period is available */ - std::pair next_priority (); - std::pair wait_priority (); + /* Waits until a suitable account outside of cooldown period is available */ + using priority_result = nano::bootstrap::account_sets::priority_result; + priority_result next_priority (); + priority_result wait_priority (); /* Gets the next account from the database */ nano::account next_database (bool should_throttle); nano::account wait_database (bool should_throttle);