From 927d1b9ae2da0c03bdee2403fdff3680c88c6030 Mon Sep 17 00:00:00 2001 From: clemahieu Date: Wed, 30 Nov 2022 15:30:56 +0000 Subject: [PATCH] Rebalancing buckets using an approximate normal distribution around 2^88-2^120 raw. (#3980) Testing min/max bounds of amount and removing logging message. --- nano/core_test/prioritization.cpp | 28 +++++++++++++++++------ nano/node/prioritization.cpp | 38 +++++++++++++++++++++---------- nano/node/prioritization.hpp | 1 + nano/rpc_test/rpc.cpp | 2 -- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/nano/core_test/prioritization.cpp b/nano/core_test/prioritization.cpp index abdf89d9..a73bdcaa 100644 --- a/nano/core_test/prioritization.cpp +++ b/nano/core_test/prioritization.cpp @@ -111,41 +111,55 @@ TEST (prioritization, construction) nano::prioritization prioritization; ASSERT_EQ (0, prioritization.size ()); ASSERT_TRUE (prioritization.empty ()); - ASSERT_EQ (129, prioritization.bucket_count ()); + ASSERT_EQ (62, prioritization.bucket_count ()); } -TEST (prioritization, insert_zero) +TEST (prioritization, index_min) +{ + nano::prioritization prioritization; + ASSERT_EQ (0, prioritization.index (std::numeric_limits::min ())); +} + +TEST (prioritization, index_max) +{ + nano::prioritization prioritization; + ASSERT_EQ (prioritization.bucket_count () - 1, prioritization.index (std::numeric_limits::max ())); +} + +TEST (prioritization, insert_Gxrb) { nano::prioritization prioritization; prioritization.push (1000, block0 ()); ASSERT_EQ (1, prioritization.size ()); - ASSERT_EQ (1, prioritization.bucket_size (110)); + ASSERT_EQ (1, prioritization.bucket_size (48)); } -TEST (prioritization, insert_one) +TEST (prioritization, insert_Mxrb) { nano::prioritization prioritization; prioritization.push (1000, block1 ()); ASSERT_EQ (1, prioritization.size ()); - ASSERT_EQ (1, prioritization.bucket_size (100)); + ASSERT_EQ (1, prioritization.bucket_size (13)); } +// Test two blocks with the same priority TEST (prioritization, insert_same_priority) { nano::prioritization prioritization; prioritization.push (1000, block0 ()); prioritization.push (1000, block2 ()); ASSERT_EQ (2, prioritization.size ()); - ASSERT_EQ (2, prioritization.bucket_size (110)); + ASSERT_EQ (2, prioritization.bucket_size (48)); } +// Test the same block inserted multiple times TEST (prioritization, insert_duplicate) { nano::prioritization prioritization; prioritization.push (1000, block0 ()); prioritization.push (1000, block0 ()); ASSERT_EQ (1, prioritization.size ()); - ASSERT_EQ (1, prioritization.bucket_size (110)); + ASSERT_EQ (1, prioritization.bucket_size (48)); } TEST (prioritization, insert_older) diff --git a/nano/node/prioritization.cpp b/nano/node/prioritization.cpp index ebe17275..81466ec8 100644 --- a/nano/node/prioritization.cpp +++ b/nano/node/prioritization.cpp @@ -50,19 +50,34 @@ void nano::prioritization::populate_schedule () nano::prioritization::prioritization (uint64_t maximum) : maximum{ maximum } { - static std::size_t constexpr bucket_count = 129; - buckets.resize (bucket_count); - nano::uint128_t minimum{ 1 }; - minimums.push_back (0); - for (auto i = 1; i < bucket_count; ++i) - { - minimums.push_back (minimum); - minimum <<= 1; - } + auto build_region = [this] (uint128_t const & begin, uint128_t const & end, size_t count) { + auto width = (end - begin) / count; + for (auto i = 0; i < count; ++i) + { + minimums.push_back (begin + i * width); + } + }; + minimums.push_back (uint128_t{ 0 }); + build_region (uint128_t{ 1 } << 88, uint128_t{ 1 } << 92, 2); + build_region (uint128_t{ 1 } << 92, uint128_t{ 1 } << 96, 4); + build_region (uint128_t{ 1 } << 96, uint128_t{ 1 } << 100, 8); + build_region (uint128_t{ 1 } << 100, uint128_t{ 1 } << 104, 16); + build_region (uint128_t{ 1 } << 104, uint128_t{ 1 } << 108, 16); + build_region (uint128_t{ 1 } << 108, uint128_t{ 1 } << 112, 8); + build_region (uint128_t{ 1 } << 112, uint128_t{ 1 } << 116, 4); + build_region (uint128_t{ 1 } << 116, uint128_t{ 1 } << 120, 2); + minimums.push_back (uint128_t{ 1 } << 120); + buckets.resize (minimums.size ()); populate_schedule (); current = schedule.begin (); } +std::size_t nano::prioritization::index (nano::uint128_t const & balance) const +{ + auto index = std::upper_bound (minimums.begin (), minimums.end (), balance) - minimums.begin () - 1; + return index; +} + /** * Push a block and its associated time into the prioritization container. * The time is given here because sideband might not exist in the case of state blocks. @@ -73,8 +88,7 @@ void nano::prioritization::push (uint64_t time, std::shared_ptr blo auto block_has_balance = block->type () == nano::block_type::state || block->type () == nano::block_type::send; debug_assert (block_has_balance || block->has_sideband ()); auto balance = block_has_balance ? block->balance () : block->sideband ().balance; - auto index = std::upper_bound (minimums.begin (), minimums.end (), balance.number ()) - 1 - minimums.begin (); - auto & bucket = buckets[index]; + auto & bucket = buckets[index (balance.number ())]; bucket.emplace (value_type{ time, block }); if (bucket.size () > std::max (decltype (maximum){ 1 }, maximum / buckets.size ())) { @@ -156,4 +170,4 @@ std::unique_ptr nano::prioritization::collect_co composite->add_component (std::make_unique (container_info{ std::to_string (i), bucket.size (), 0 })); } return composite; -} \ No newline at end of file +} diff --git a/nano/node/prioritization.hpp b/nano/node/prioritization.hpp index e925b379..1629327a 100644 --- a/nano/node/prioritization.hpp +++ b/nano/node/prioritization.hpp @@ -63,6 +63,7 @@ public: std::size_t bucket_size (std::size_t index) const; bool empty () const; void dump () const; + std::size_t index (nano::uint128_t const & balance) const; std::unique_ptr collect_container_info (std::string const &); }; diff --git a/nano/rpc_test/rpc.cpp b/nano/rpc_test/rpc.cpp index 63202b56..ad9a0643 100644 --- a/nano/rpc_test/rpc.cpp +++ b/nano/rpc_test/rpc.cpp @@ -7581,6 +7581,4 @@ TEST (node, election_scheduler_container_info) request.put ("type", "objects"); auto response = wait_response (system, rpc_ctx, request); auto es = response.get_child ("node").get_child ("election_scheduler"); - ASSERT_EQ (es.get_child ("manual_queue").get ("count"), "0"); - ASSERT_EQ (es.get_child ("priority").get_child ("128").get ("count"), "1"); }