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:
Sergey Kroshnin 2019-02-01 15:28:31 +03:00 committed by GitHub
commit f716f82067
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 67 additions and 43 deletions

View file

@ -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,41 +666,31 @@ 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 successor (node.ledger.successor (transaction, nano::uint512_union (message_a.block->previous (), message_a.block->root ())));
if (successor != nullptr)
auto hash (message_a.block->hash ());
if (!node.network.send_votes_cache (hash, sender))
{
auto same_block (successor->hash () == message_a.block->hash ());
confirm_block (transaction, node, sender, std::move (successor), !same_block);
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 () == 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))
if (!node.network.send_votes_cache (root_hash.first, sender) && node.store.block_exists (transaction, root_hash.first))
{
// Search in cache
auto votes (node.votes_cache.find (root_hash.first));
if (votes.empty ())
{
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);
}
}
blocks_bundle.push_back (root_hash.first);
}
else
{
@ -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++;

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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);

View file

@ -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 ();

View file

@ -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)
{

View file

@ -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 &);