Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

active_transaction.roots bounding by config instead of confirmation rate #2051

Merged
merged 7 commits into from
Jun 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 3 additions & 77 deletions nano/core_test/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,69 +6,6 @@

using namespace std::chrono_literals;

TEST (transaction_counter, validate)
{
auto now = std::chrono::steady_clock::now ();
nano::transaction_counter counter;
auto count (0);
ASSERT_EQ (count, counter.get_rate ());
while (std::chrono::steady_clock::now () < now + 1s)
{
count++;
counter.add ();
}
counter.trend_sample ();
ASSERT_EQ (count, counter.get_rate ());
}

TEST (active_transactions, long_unconfirmed_size)
{
nano::system system;
nano::node_config node_config (24000, system.logging);
node_config.enable_voting = false;
auto & node1 = *system.add_node (node_config);
auto & wallet (*system.wallet (0));
nano::genesis genesis;
wallet.insert_adhoc (nano::test_genesis_key.prv);
nano::keypair key1;
auto send1 (wallet.send_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub, nano::Mxrb_ratio));
auto send2 (wallet.send_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub, nano::Mxrb_ratio));
auto send3 (wallet.send_action (nano::test_genesis_key.pub, nano::test_genesis_key.pub, nano::Mxrb_ratio));
system.deadline_set (10s);
while (node1.active.size () != 3)
{
ASSERT_NO_ERROR (system.poll ());
}
auto done (false);
while (!done)
{
ASSERT_FALSE (node1.active.empty ());
{
std::lock_guard<std::mutex> guard (node1.active.mutex);
done = node1.active.long_unconfirmed_size == 3;
}
ASSERT_NO_ERROR (system.poll ());
}
{
//since send1 is long_unconfirmed the other two should be as well
std::lock_guard<std::mutex> lock (node1.active.mutex);
ASSERT_EQ (node1.active.long_unconfirmed_size, 3);
}
{
std::lock_guard<std::mutex> guard (node1.active.mutex);
auto existing (node1.active.roots.find (send1->qualified_root ()));
ASSERT_NE (node1.active.roots.end (), existing);
//force election to appear confirmed
auto election (existing->election);
election->confirm_once ();
}
{
//only 2 should appear unconfirmed now
std::lock_guard<std::mutex> lock (node1.active.mutex);
ASSERT_EQ (node1.active.long_unconfirmed_size, 2);
}
}

TEST (active_transactions, adjusted_difficulty_priority)
{
nano::system system;
Expand All @@ -77,7 +14,6 @@ TEST (active_transactions, adjusted_difficulty_priority)
auto & node1 = *system.add_node (node_config);
nano::genesis genesis;
nano::keypair key1, key2, key3;
auto transaction (node1.store.tx_begin_read ());

auto send1 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, genesis.hash (), nano::test_genesis_key.pub, nano::genesis_amount - 10 * nano::xrb_ratio, key1.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (genesis.hash ())));
auto send2 (std::make_shared<nano::state_block> (nano::test_genesis_key.pub, send1->hash (), nano::test_genesis_key.pub, nano::genesis_amount - 20 * nano::xrb_ratio, key2.pub, nano::test_genesis_key.prv, nano::test_genesis_key.pub, system.work.generate (send1->hash ())));
Expand Down Expand Up @@ -153,6 +89,7 @@ TEST (active_transactions, keep_local)
nano::system system;
nano::node_config node_config (24000, system.logging);
node_config.enable_voting = false;
node_config.active_elections_size = 3; //bound to 3, wont drop wallet created transactions, but good to test dropping remote
auto & node1 = *system.add_node (node_config, delay_frontier_confirmation_height_updating);
auto & wallet (*system.wallet (0));
nano::genesis genesis;
Expand Down Expand Up @@ -190,18 +127,6 @@ TEST (active_transactions, keep_local)
{
ASSERT_NO_ERROR (system.poll ());
}
auto done (false);
//wait for all to be long_unconfirmed
system.deadline_set (10s);
while (!done)
{
ASSERT_FALSE (node1.active.empty ());
{
std::lock_guard<std::mutex> guard (node1.active.mutex);
done = node1.active.long_unconfirmed_size == 4;
}
ASSERT_NO_ERROR (system.poll ());
}
auto send5 (wallet.send_action (nano::test_genesis_key.pub, key1.pub, node1.config.receive_minimum.number ()));
node1.active.start (send5);
//drop two lowest non-wallet managed active_transactions before inserting a new into active as all are long_unconfirmed
Expand All @@ -219,6 +144,7 @@ TEST (active_transactions, prioritize_chains)
nano::system system;
nano::node_config node_config (24000, system.logging);
node_config.enable_voting = false;
node_config.active_elections_size = 4; //bound to 3, wont drop wallet created transactions, but good to test dropping remote
auto & node1 = *system.add_node (node_config, delay_frontier_confirmation_height_updating);
nano::genesis genesis;
nano::keypair key1, key2, key3;
Expand Down Expand Up @@ -266,7 +192,7 @@ TEST (active_transactions, prioritize_chains)
{
ASSERT_NO_ERROR (system.poll ());
}

system.deadline_set (10s);
bool done (false);
//wait for all to be long_unconfirmed
while (!done)
Expand Down
6 changes: 6 additions & 0 deletions nano/core_test/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@ TEST (node_config, v16_v17_upgrade)
ASSERT_FALSE (tree.get_optional_child ("diagnostics"));
ASSERT_FALSE (tree.get_optional_child ("use_memory_pools"));
ASSERT_FALSE (tree.get_optional_child ("confirmation_history_size"));
ASSERT_FALSE (tree.get_optional_child ("active_elections_size"));

config.deserialize_json (upgraded, tree);
// The config options should be added after the upgrade
Expand All @@ -725,6 +726,7 @@ TEST (node_config, v16_v17_upgrade)
ASSERT_TRUE (!!tree.get_optional_child ("diagnostics"));
ASSERT_TRUE (!!tree.get_optional_child ("use_memory_pools"));
ASSERT_TRUE (!!tree.get_optional_child ("confirmation_history_size"));
ASSERT_TRUE (!!tree.get_optional_child ("active_elections_size"));

ASSERT_TRUE (upgraded);
auto version (tree.get<std::string> ("version"));
Expand Down Expand Up @@ -761,6 +763,7 @@ TEST (node_config, v17_values)
tree.put_child ("diagnostics", diagnostics_l);
tree.put ("use_memory_pools", true);
tree.put ("confirmation_history_size", 2048);
tree.put ("active_elections_size", 8000);
}

config.deserialize_json (upgraded, tree);
Expand All @@ -776,6 +779,7 @@ TEST (node_config, v17_values)
ASSERT_TRUE (config.diagnostics_config.txn_tracking.ignore_writes_below_block_processor_max_time);
ASSERT_TRUE (config.use_memory_pools);
ASSERT_EQ (config.confirmation_history_size, 2048);
ASSERT_EQ (config.active_elections_size, 8000);

// Check config is correct with other values
tree.put ("tcp_io_timeout", std::numeric_limits<unsigned long>::max () - 100);
Expand All @@ -794,6 +798,7 @@ TEST (node_config, v17_values)
tree.replace_child ("diagnostics", diagnostics_l);
tree.put ("use_memory_pools", false);
tree.put ("confirmation_history_size", std::numeric_limits<unsigned long long>::max ());
tree.put ("active_elections_size", std::numeric_limits<unsigned long long>::max ());

upgraded = false;
config.deserialize_json (upgraded, tree);
Expand All @@ -811,6 +816,7 @@ TEST (node_config, v17_values)
ASSERT_FALSE (config.diagnostics_config.txn_tracking.ignore_writes_below_block_processor_max_time);
ASSERT_FALSE (config.use_memory_pools);
ASSERT_EQ (config.confirmation_history_size, std::numeric_limits<unsigned long long>::max ());
ASSERT_EQ (config.active_elections_size, std::numeric_limits<unsigned long long>::max ());
}

// Regression test to ensure that deserializing includes changes node via get_required_child
Expand Down
74 changes: 1 addition & 73 deletions nano/node/active_transactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,7 @@ bool nano::active_transactions::add (std::shared_ptr<nano::block> block_a, std::
error = existing != roots.end ();
if (error)
{
counter.add ();
if (should_flush ())
if (roots.size () >= node.config.active_elections_size)
{
flush_lowest ();
}
Expand Down Expand Up @@ -662,52 +661,6 @@ void nano::active_transactions::erase (nano::block const & block_a)
}
}

bool nano::active_transactions::should_flush ()
{
bool result (false);
counter.trend_sample ();
size_t minimum_size (1);
auto rate (counter.get_rate ());
if (roots.size () > 100000)
{
return true;
}
if (rate == 0)
{
//set minimum size to 4 for test network
minimum_size = node.network_params.network.is_test_network () ? 4 : 512;
}
else
{
minimum_size = rate * 512;
}
if (roots.size () >= minimum_size)
{
if (rate <= 10)
{
if (roots.size () * .75 < long_unconfirmed_size)
{
result = true;
}
}
else if (rate <= 100)
{
if (roots.size () * .50 < long_unconfirmed_size)
{
result = true;
}
}
else if (rate <= 1000)
{
if (roots.size () * .25 < long_unconfirmed_size)
{
result = true;
}
}
}
return result;
}

void nano::active_transactions::flush_lowest ()
{
size_t count (0);
Expand Down Expand Up @@ -824,29 +777,4 @@ std::unique_ptr<seq_con_info_component> collect_seq_con_info (active_transaction
composite->add_component (std::make_unique<seq_con_info_leaf> (seq_con_info{ "priority_cementable_frontiers_count", active_transactions.priority_cementable_frontiers_size (), sizeof (nano::cementable_account) }));
return composite;
}

void transaction_counter::add ()
{
std::lock_guard<std::mutex> lock (mutex);
counter++;
}

void transaction_counter::trend_sample ()
{
std::lock_guard<std::mutex> lock (mutex);
auto now (std::chrono::steady_clock::now ());
if (now >= trend_last + 1s && counter != 0)
{
auto elapsed = std::chrono::duration_cast<std::chrono::seconds> (now - trend_last);
rate = counter / elapsed.count ();
counter = 0;
trend_last = std::chrono::steady_clock::now ();
}
}

double transaction_counter::get_rate ()
{
std::lock_guard<std::mutex> lock (mutex);
return rate;
}
}
23 changes: 0 additions & 23 deletions nano/node/active_transactions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,6 @@ class election_status final
election_status_type type;
};

class transaction_counter final
{
public:
// increment counter
void add ();
// clear counter and reset trend_last after calculating a new rate, guarded to only run once a sec
void trend_sample ();
double get_rate ();

private:
std::chrono::steady_clock::time_point trend_last = std::chrono::steady_clock::now ();
size_t counter = 0;
// blocks/sec confirmed
double rate = 0;
std::mutex mutex;
};

class cementable_account final
{
public:
Expand Down Expand Up @@ -108,11 +91,6 @@ class active_transactions final
uint64_t active_difficulty ();
std::deque<std::shared_ptr<nano::block>> list_blocks (bool = false);
void erase (nano::block const &);
//check if we should flush
//if counter.rate == 0 set minimum_size before considering flushing to 4 for testing convenience
//else minimum_size is rate * 10
//when roots.size > minimum_size check counter.rate and adjusted expected percentage long unconfirmed before kicking in
bool should_flush ();
//drop 2 from roots based on adjusted_difficulty
void flush_lowest ();
bool empty ();
Expand All @@ -132,7 +110,6 @@ class active_transactions final
std::unordered_map<nano::block_hash, std::shared_ptr<nano::election>> blocks;
std::deque<nano::election_status> list_confirmed ();
std::deque<nano::election_status> confirmed;
nano::transaction_counter counter;
nano::node & node;
std::mutex mutex;
// Maximum number of conflicts to vote on per interval, lowest root hash first
Expand Down
8 changes: 8 additions & 0 deletions nano/node/nodeconfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ nano::error nano::node_config::serialize_json (nano::jsonconfig & json) const
diagnostics_config.serialize_json (diagnostics_l);
json.put_child ("diagnostics", diagnostics_l);
json.put ("confirmation_history_size", confirmation_history_size);
json.put ("active_elections_size", active_elections_size);

return json.get_error ();
}
Expand Down Expand Up @@ -249,6 +250,7 @@ bool nano::node_config::upgrade_json (unsigned version_a, nano::jsonconfig & jso
json.put ("vote_generator_delay", vote_generator_delay.count ());
json.put ("use_memory_pools", use_memory_pools);
json.put ("confirmation_history_size", confirmation_history_size);
json.put ("active_elections_size", active_elections_size);
}
case 17:
break;
Expand Down Expand Up @@ -398,6 +400,8 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco
json.get<bool> ("use_memory_pools", use_memory_pools);
json.get<size_t> ("confirmation_history_size", confirmation_history_size);

json.get<size_t> ("active_elections_size", active_elections_size);
nano::network_params network;
// Validate ranges
if (online_weight_quorum > 100)
{
Expand All @@ -411,6 +415,10 @@ nano::error nano::node_config::deserialize_json (bool & upgraded_a, nano::jsonco
{
json.get_error ().set ("io_threads must be non-zero");
}
if (active_elections_size <= 250 && !network.network.is_test_network ())
{
json.get_error ().set ("active_elections_size must be grater than 250");
}
}
catch (std::runtime_error const & ex)
{
Expand Down
1 change: 1 addition & 0 deletions nano/node/nodeconfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class node_config
/** Timeout for initiated async operations */
std::chrono::seconds tcp_io_timeout{ (network_params.network.is_test_network () && !is_sanitizer_build) ? std::chrono::seconds (5) : std::chrono::seconds (15) };
std::chrono::nanoseconds pow_sleep_interval{ 0 };
size_t active_elections_size{ 8000 };
/** Default maximum incoming TCP connections, including realtime network & bootstrap */
unsigned tcp_incoming_connections_max{ 1024 };
bool use_memory_pools{ true };
Expand Down