Improve votes cache usage (#1678)
* Improve votes cache usage Serch block in cache before dist search * Fix code * Add wallets.reps_count * Count resp for deterministic_insert () & insert_ahdoc () * Use ++reps_count instead of reps_count++
This commit is contained in:
		
					parent
					
						
							
								daa3754bac
							
						
					
				
			
			
				commit
				
					
						f716f82067
					
				
			
		
					 8 changed files with 67 additions and 43 deletions
				
			
		| 
						 | 
				
			
			@ -334,6 +334,22 @@ void nano::network::confirm_hashes (nano::transaction const & transaction_a, nan
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool nano::network::send_votes_cache (nano::block_hash const & hash_a, nano::endpoint const & peer_a)
 | 
			
		||||
{
 | 
			
		||||
	// Search in cache
 | 
			
		||||
	auto votes (node.votes_cache.find (hash_a));
 | 
			
		||||
	// Send from cache
 | 
			
		||||
	for (auto & vote : votes)
 | 
			
		||||
	{
 | 
			
		||||
		nano::confirm_ack confirm (vote);
 | 
			
		||||
		auto vote_bytes = confirm.to_bytes ();
 | 
			
		||||
		confirm_send (confirm, vote_bytes, peer_a);
 | 
			
		||||
	}
 | 
			
		||||
	// Returns true if votes were sent
 | 
			
		||||
	bool result (!votes.empty ());
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::network::republish_block (std::shared_ptr<nano::block> block)
 | 
			
		||||
{
 | 
			
		||||
	auto hash (block->hash ());
 | 
			
		||||
| 
						 | 
				
			
			@ -650,43 +666,33 @@ public:
 | 
			
		|||
		node.stats.inc (nano::stat::type::message, nano::stat::detail::confirm_req, nano::stat::dir::in);
 | 
			
		||||
		node.peers.contacted (sender, message_a.header.version_using);
 | 
			
		||||
		// Don't load nodes with disabled voting
 | 
			
		||||
		if (node.config.enable_voting)
 | 
			
		||||
		if (node.config.enable_voting && node.wallets.reps_count)
 | 
			
		||||
		{
 | 
			
		||||
			auto transaction (node.store.tx_begin_read ());
 | 
			
		||||
			if (message_a.block != nullptr)
 | 
			
		||||
			{
 | 
			
		||||
				auto hash (message_a.block->hash ());
 | 
			
		||||
				if (!node.network.send_votes_cache (hash, sender))
 | 
			
		||||
				{
 | 
			
		||||
					auto transaction (node.store.tx_begin_read ());
 | 
			
		||||
					auto successor (node.ledger.successor (transaction, nano::uint512_union (message_a.block->previous (), message_a.block->root ())));
 | 
			
		||||
					if (successor != nullptr)
 | 
			
		||||
					{
 | 
			
		||||
					auto same_block (successor->hash () == message_a.block->hash ());
 | 
			
		||||
						auto same_block (successor->hash () == hash);
 | 
			
		||||
						confirm_block (transaction, node, sender, std::move (successor), !same_block);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (!message_a.roots_hashes.empty ())
 | 
			
		||||
			{
 | 
			
		||||
				auto transaction (node.store.tx_begin_read ());
 | 
			
		||||
				std::vector<nano::block_hash> blocks_bundle;
 | 
			
		||||
				for (auto & root_hash : message_a.roots_hashes)
 | 
			
		||||
				{
 | 
			
		||||
					if (node.store.block_exists (transaction, root_hash.first))
 | 
			
		||||
					{
 | 
			
		||||
						// Search in cache
 | 
			
		||||
						auto votes (node.votes_cache.find (root_hash.first));
 | 
			
		||||
						if (votes.empty ())
 | 
			
		||||
					if (!node.network.send_votes_cache (root_hash.first, sender) && node.store.block_exists (transaction, root_hash.first))
 | 
			
		||||
					{
 | 
			
		||||
						blocks_bundle.push_back (root_hash.first);
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
						{
 | 
			
		||||
							// Send from cache
 | 
			
		||||
							for (auto & vote : votes)
 | 
			
		||||
							{
 | 
			
		||||
								nano::confirm_ack confirm (vote);
 | 
			
		||||
								auto vote_bytes = confirm.to_bytes ();
 | 
			
		||||
								node.network.confirm_send (confirm, vote_bytes, sender);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						nano::block_hash successor (0);
 | 
			
		||||
						// Search for block root
 | 
			
		||||
| 
						 | 
				
			
			@ -701,22 +707,10 @@ public:
 | 
			
		|||
						}
 | 
			
		||||
						if (!successor.is_zero ())
 | 
			
		||||
						{
 | 
			
		||||
							// Search in cache
 | 
			
		||||
							auto votes (node.votes_cache.find (successor));
 | 
			
		||||
							if (votes.empty ())
 | 
			
		||||
							if (!node.network.send_votes_cache (successor, sender))
 | 
			
		||||
							{
 | 
			
		||||
								blocks_bundle.push_back (successor);
 | 
			
		||||
							}
 | 
			
		||||
							else
 | 
			
		||||
							{
 | 
			
		||||
								// Send from cache
 | 
			
		||||
								for (auto & vote : votes)
 | 
			
		||||
								{
 | 
			
		||||
									nano::confirm_ack confirm (vote);
 | 
			
		||||
									auto vote_bytes = confirm.to_bytes ();
 | 
			
		||||
									node.network.confirm_send (confirm, vote_bytes, sender);
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
							auto successor_block (node.store.block_get (transaction, successor));
 | 
			
		||||
							assert (successor_block != nullptr);
 | 
			
		||||
							node.network.republish_block (std::move (successor_block), sender);
 | 
			
		||||
| 
						 | 
				
			
			@ -1811,7 +1805,9 @@ void nano::block_processor::process_batch (std::unique_lock<std::mutex> & lock_a
 | 
			
		|||
			{
 | 
			
		||||
				// Replace our block with the winner and roll back any dependent blocks
 | 
			
		||||
				BOOST_LOG (node.log) << boost::str (boost::format ("Rolling back %1% and replacing with %2%") % successor->hash ().to_string () % hash.to_string ());
 | 
			
		||||
				node.ledger.rollback (transaction, successor->hash ());
 | 
			
		||||
				std::vector<nano::block_hash> rollback_list;
 | 
			
		||||
				node.ledger.rollback (transaction, successor->hash (), rollback_list);
 | 
			
		||||
				BOOST_LOG (node.log) << boost::str (boost::format ("%1% blocks rolled back") % rollback_list.size ());
 | 
			
		||||
				lock_a.lock ();
 | 
			
		||||
				// Prevent rolled back blocks second insertion
 | 
			
		||||
				auto inserted (rolled_back.insert (nano::rolled_hash{ std::chrono::steady_clock::now (), successor->hash () }));
 | 
			
		||||
| 
						 | 
				
			
			@ -1826,6 +1822,11 @@ void nano::block_processor::process_batch (std::unique_lock<std::mutex> & lock_a
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
				lock_a.unlock ();
 | 
			
		||||
				// Deleting from votes cache
 | 
			
		||||
				for (auto & i : rollback_list)
 | 
			
		||||
				{
 | 
			
		||||
					node.votes_cache.remove (i);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		number_of_blocks_processed++;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -334,6 +334,7 @@ public:
 | 
			
		|||
	void send_confirm_req (nano::endpoint const &, std::shared_ptr<nano::block>);
 | 
			
		||||
	void send_confirm_req_hashes (nano::endpoint const &, std::vector<std::pair<nano::block_hash, nano::block_hash>> const &);
 | 
			
		||||
	void confirm_hashes (nano::transaction const &, nano::endpoint const &, std::vector<nano::block_hash>);
 | 
			
		||||
	bool send_votes_cache (nano::block_hash const &, nano::endpoint const &);
 | 
			
		||||
	void send_buffer (uint8_t const *, size_t, nano::endpoint const &, std::function<void(boost::system::error_code const &, size_t)>);
 | 
			
		||||
	nano::endpoint endpoint ();
 | 
			
		||||
	nano::udp_buffer buffer_container;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,6 +141,12 @@ std::vector<std::shared_ptr<nano::vote>> nano::votes_cache::find (nano::block_ha
 | 
			
		|||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::votes_cache::remove (nano::block_hash const & hash_a)
 | 
			
		||||
{
 | 
			
		||||
	std::lock_guard<std::mutex> lock (cache_mutex);
 | 
			
		||||
	cache.get<1> ().erase (hash_a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace nano
 | 
			
		||||
{
 | 
			
		||||
std::unique_ptr<seq_con_info_component> collect_seq_con_info (vote_generator & vote_generator, const std::string & name)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,6 +53,7 @@ class votes_cache
 | 
			
		|||
public:
 | 
			
		||||
	void add (std::shared_ptr<nano::vote> const &);
 | 
			
		||||
	std::vector<std::shared_ptr<nano::vote>> find (nano::block_hash const &);
 | 
			
		||||
	void remove (nano::block_hash const &);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	std::mutex cache_mutex;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -805,6 +805,7 @@ nano::public_key nano::wallet::deterministic_insert (nano::transaction const & t
 | 
			
		|||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> lock (representatives_mutex);
 | 
			
		||||
			representatives.insert (key);
 | 
			
		||||
			++wallets.reps_count;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return key;
 | 
			
		||||
| 
						 | 
				
			
			@ -847,6 +848,7 @@ nano::public_key nano::wallet::insert_adhoc (nano::transaction const & transacti
 | 
			
		|||
		{
 | 
			
		||||
			std::lock_guard<std::mutex> lock (representatives_mutex);
 | 
			
		||||
			representatives.insert (key);
 | 
			
		||||
			++wallets.reps_count;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return key;
 | 
			
		||||
| 
						 | 
				
			
			@ -1605,6 +1607,7 @@ void nano::wallets::clear_send_ids (nano::transaction const & transaction_a)
 | 
			
		|||
void nano::wallets::compute_reps ()
 | 
			
		||||
{
 | 
			
		||||
	std::lock_guard<std::mutex> lock (mutex);
 | 
			
		||||
	reps_count = 0;
 | 
			
		||||
	auto ledger_transaction (node.store.tx_begin_read ());
 | 
			
		||||
	auto transaction (tx_begin_read ());
 | 
			
		||||
	for (auto i (items.begin ()), n (items.end ()); i != n; ++i)
 | 
			
		||||
| 
						 | 
				
			
			@ -1617,6 +1620,7 @@ void nano::wallets::compute_reps ()
 | 
			
		|||
			if (node.ledger.weight (ledger_transaction, account) >= node.config.vote_minimum.number ())
 | 
			
		||||
			{
 | 
			
		||||
				representatives_l.insert (account);
 | 
			
		||||
				++reps_count;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		std::lock_guard<std::mutex> representatives_lock (wallet.representatives_mutex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -200,6 +200,7 @@ public:
 | 
			
		|||
	boost::thread thread;
 | 
			
		||||
	static nano::uint128_t const generate_priority;
 | 
			
		||||
	static nano::uint128_t const high_priority;
 | 
			
		||||
	std::atomic<uint64_t> reps_count{ 0 };
 | 
			
		||||
 | 
			
		||||
	/** Start read-write transaction */
 | 
			
		||||
	nano::transaction tx_begin_write ();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,10 @@ namespace
 | 
			
		|||
class rollback_visitor : public nano::block_visitor
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	rollback_visitor (nano::transaction const & transaction_a, nano::ledger & ledger_a) :
 | 
			
		||||
	rollback_visitor (nano::transaction const & transaction_a, nano::ledger & ledger_a, std::vector<nano::block_hash> & list_a) :
 | 
			
		||||
	transaction (transaction_a),
 | 
			
		||||
	ledger (ledger_a)
 | 
			
		||||
	ledger (ledger_a),
 | 
			
		||||
	list (list_a)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	virtual ~rollback_visitor () = default;
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +25,7 @@ public:
 | 
			
		|||
		nano::pending_key key (block_a.hashables.destination, hash);
 | 
			
		||||
		while (ledger.store.pending_get (transaction, key, pending))
 | 
			
		||||
		{
 | 
			
		||||
			ledger.rollback (transaction, ledger.latest (transaction, block_a.hashables.destination));
 | 
			
		||||
			ledger.rollback (transaction, ledger.latest (transaction, block_a.hashables.destination), list);
 | 
			
		||||
		}
 | 
			
		||||
		nano::account_info info;
 | 
			
		||||
		auto error (ledger.store.account_get (transaction, pending.source, info));
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +115,7 @@ public:
 | 
			
		|||
			nano::pending_key key (block_a.hashables.link, hash);
 | 
			
		||||
			while (!ledger.store.pending_exists (transaction, key))
 | 
			
		||||
			{
 | 
			
		||||
				ledger.rollback (transaction, ledger.latest (transaction, block_a.hashables.link));
 | 
			
		||||
				ledger.rollback (transaction, ledger.latest (transaction, block_a.hashables.link), list);
 | 
			
		||||
			}
 | 
			
		||||
			ledger.store.pending_del (transaction, key);
 | 
			
		||||
			ledger.stats.inc (nano::stat::type::rollback, nano::stat::detail::send);
 | 
			
		||||
| 
						 | 
				
			
			@ -148,6 +149,7 @@ public:
 | 
			
		|||
	}
 | 
			
		||||
	nano::transaction const & transaction;
 | 
			
		||||
	nano::ledger & ledger;
 | 
			
		||||
	std::vector<nano::block_hash> & list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ledger_processor : public nano::block_visitor
 | 
			
		||||
| 
						 | 
				
			
			@ -824,21 +826,28 @@ nano::uint128_t nano::ledger::weight (nano::transaction const & transaction_a, n
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// Rollback blocks until `block_a' doesn't exist
 | 
			
		||||
void nano::ledger::rollback (nano::transaction const & transaction_a, nano::block_hash const & block_a)
 | 
			
		||||
void nano::ledger::rollback (nano::transaction const & transaction_a, nano::block_hash const & block_a, std::vector<nano::block_hash> & list_a)
 | 
			
		||||
{
 | 
			
		||||
	assert (store.block_exists (transaction_a, block_a));
 | 
			
		||||
	auto account_l (account (transaction_a, block_a));
 | 
			
		||||
	rollback_visitor rollback (transaction_a, *this);
 | 
			
		||||
	rollback_visitor rollback (transaction_a, *this, list_a);
 | 
			
		||||
	nano::account_info info;
 | 
			
		||||
	while (store.block_exists (transaction_a, block_a))
 | 
			
		||||
	{
 | 
			
		||||
		auto latest_error (store.account_get (transaction_a, account_l, info));
 | 
			
		||||
		assert (!latest_error);
 | 
			
		||||
		auto block (store.block_get (transaction_a, info.head));
 | 
			
		||||
		list_a.push_back (info.head);
 | 
			
		||||
		block->visit (rollback);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void nano::ledger::rollback (nano::transaction const & transaction_a, nano::block_hash const & block_a)
 | 
			
		||||
{
 | 
			
		||||
	std::vector<nano::block_hash> rollback_list;
 | 
			
		||||
	rollback (transaction_a, block_a, rollback_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return account containing hash
 | 
			
		||||
nano::account nano::ledger::account (nano::transaction const & transaction_a, nano::block_hash const & hash_a)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,6 +38,7 @@ public:
 | 
			
		|||
	nano::block_hash block_destination (nano::transaction const &, nano::block const &);
 | 
			
		||||
	nano::block_hash block_source (nano::transaction const &, nano::block const &);
 | 
			
		||||
	nano::process_return process (nano::transaction const &, nano::block const &, nano::signature_verification = nano::signature_verification::unknown);
 | 
			
		||||
	void rollback (nano::transaction const &, nano::block_hash const &, std::vector<nano::block_hash> &);
 | 
			
		||||
	void rollback (nano::transaction const &, nano::block_hash const &);
 | 
			
		||||
	void change_latest (nano::transaction const &, nano::account const &, nano::block_hash const &, nano::account const &, nano::uint128_union const &, uint64_t, bool = false, nano::epoch = nano::epoch::epoch_0);
 | 
			
		||||
	void dump_account_chain (nano::account const &);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue