ledger::supply is a hotspot, so we memoize and update periodically. (#824)

This commit is contained in:
cryptocode 2018-04-25 19:56:09 +02:00 committed by clemahieu
commit c942010228
6 changed files with 113 additions and 26 deletions

View file

@ -1447,6 +1447,29 @@ TEST (ledger, latest_root)
ASSERT_EQ (send.hash (), ledger.latest_root (transaction, rai::test_genesis_key.pub));
}
TEST (ledger, supply_cache)
{
bool init (false);
rai::block_store store (init, rai::unique_path ());
ASSERT_TRUE (!init);
rai::ledger ledger (store, 40);
{
rai::transaction transaction (store.environment, nullptr, true);
rai::genesis genesis;
genesis.initialize (transaction, store);
rai::keypair key2;
rai::account_info info1;
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info1));
rai::send_block send (info1.head, key2.pub, std::numeric_limits<rai::uint128_t>::max () - 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ledger.process (transaction, send);
}
// Cached (default)
ASSERT_NE (10, ledger.supply.circulating_get ());
// Uncached
ASSERT_EQ (10, ledger.supply.circulating_get (true));
}
TEST (ledger, inactive_supply)
{
bool init (false);
@ -1463,12 +1486,11 @@ TEST (ledger, inactive_supply)
rai::send_block send (info1.head, key2.pub, std::numeric_limits<rai::uint128_t>::max () - 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ledger.process (transaction, send);
}
rai::transaction transaction (store.environment, nullptr, false);
ASSERT_EQ (10, ledger.supply (transaction));
ledger.inactive_supply = 60;
ASSERT_EQ (0, ledger.supply (transaction));
ledger.inactive_supply = 0;
ASSERT_EQ (50, ledger.supply (transaction));
ASSERT_EQ (10, ledger.supply.circulating_get (true));
ledger.supply.inactive_set (60);
ASSERT_EQ (0, ledger.supply.circulating_get (true));
ledger.supply.inactive_set (0);
ASSERT_EQ (50, ledger.supply.circulating_get (true));
}
TEST (ledger, change_representative_move_representation)

View file

@ -38,7 +38,7 @@ TEST (node, inactive_supply)
rai::work_pool work (std::numeric_limits<unsigned>::max (), nullptr);
config.inactive_supply = 10;
auto node (std::make_shared<rai::node> (init, *service, path, alarm, config, work));
ASSERT_EQ (10, node->ledger.inactive_supply);
ASSERT_EQ (10, node->ledger.supply.inactive_get ());
node->stop ();
}

View file

@ -495,12 +495,52 @@ bool rai::shared_ptr_block_hash::operator() (std::shared_ptr<rai::block> const &
return *lhs == *rhs;
}
rai::supply::supply (rai::ledger & ledger_a, rai::uint128_t const & inactive_supply_a) :
ledger (ledger_a),
inactive_supply (inactive_supply_a)
{
circulating_update ();
}
rai::uint128_t rai::supply::circulating_get (bool force_update)
{
rai::uint128_t supply;
{
std::unique_lock<std::mutex> lock (mutex);
if (force_update)
{
update_cache ();
}
supply = cached_supply;
}
return supply;
}
void rai::supply::circulating_update ()
{
std::unique_lock<std::mutex> lock (mutex);
update_cache ();
}
void rai::supply::update_cache ()
{
if (ledger.store.environment)
{
rai::transaction transaction (ledger.store.environment, nullptr, false);
auto unallocated (ledger.account_balance (transaction, rai::genesis_account));
auto burned (ledger.account_pending (transaction, 0));
auto absolute_supply (rai::genesis_amount - unallocated - burned);
auto adjusted_supply (absolute_supply - inactive_supply);
cached_supply = adjusted_supply <= absolute_supply ? adjusted_supply : 0;
}
}
rai::ledger::ledger (rai::block_store & store_a, rai::uint128_t const & inactive_supply_a, rai::block_hash const & state_block_parse_canary_a, rai::block_hash const & state_block_generate_canary_a) :
store (store_a),
inactive_supply (inactive_supply_a),
check_bootstrap_weights (true),
state_block_parse_canary (state_block_parse_canary_a),
state_block_generate_canary (state_block_generate_canary_a)
state_block_generate_canary (state_block_generate_canary_a),
supply (*this, inactive_supply_a)
{
}
@ -577,16 +617,6 @@ rai::process_return rai::ledger::process (MDB_txn * transaction_a, rai::block co
return processor.result;
}
// Money supply for heuristically calculating vote percentages
rai::uint128_t rai::ledger::supply (MDB_txn * transaction_a)
{
auto unallocated (account_balance (transaction_a, rai::genesis_account));
auto burned (account_pending (transaction_a, 0));
auto absolute_supply (rai::genesis_amount - unallocated - burned);
auto adjusted_supply (absolute_supply - inactive_supply);
return adjusted_supply <= absolute_supply ? adjusted_supply : 0;
}
rai::block_hash rai::ledger::representative (MDB_txn * transaction_a, rai::block_hash const & hash_a)
{
auto result (representative_calculated (transaction_a, hash_a));

View file

@ -12,7 +12,29 @@ public:
size_t operator() (std::shared_ptr<rai::block> const &) const;
bool operator() (std::shared_ptr<rai::block> const &, std::shared_ptr<rai::block> const &) const;
};
class ledger;
class supply
{
public:
supply (rai::ledger & ledger_a, rai::uint128_t const & inactive_supply_a);
rai::uint128_t circulating_get (bool force_update = false);
void circulating_update ();
inline rai::uint128_t inactive_get () const
{
return inactive_supply;
};
inline void inactive_set (rai::uint128_t const & inactive_supply_a)
{
inactive_supply = inactive_supply_a;
};
private:
void update_cache ();
rai::ledger & ledger;
rai::uint128_t inactive_supply;
rai::uint128_t cached_supply;
std::mutex mutex;
};
class ledger
{
public:
@ -38,7 +60,6 @@ public:
bool is_send (MDB_txn *, rai::state_block const &);
rai::block_hash block_destination (MDB_txn *, rai::block const &);
rai::block_hash block_source (MDB_txn *, rai::block const &);
rai::uint128_t supply (MDB_txn *);
rai::process_return process (MDB_txn *, rai::block const &);
void rollback (MDB_txn *, rai::block_hash const &);
void change_latest (MDB_txn *, rai::account const &, rai::block_hash const &, rai::account const &, rai::uint128_union const &, uint64_t, bool = false);
@ -49,11 +70,11 @@ public:
bool state_block_generation_enabled (MDB_txn *);
static rai::uint128_t const unit;
rai::block_store & store;
rai::uint128_t inactive_supply;
std::unordered_map<rai::account, rai::uint128_t> bootstrap_weights;
uint64_t bootstrap_weight_max_blocks;
std::atomic<bool> check_bootstrap_weights;
rai::block_hash state_block_parse_canary;
rai::block_hash state_block_generate_canary;
rai::supply supply;
};
};

View file

@ -1603,7 +1603,7 @@ online_reps (*this)
{
rai::transaction transaction (store.environment, nullptr, false);
rep_weight = ledger.weight (transaction, vote_a->account);
min_rep_weight = ledger.supply (transaction) / 1000;
min_rep_weight = ledger.supply.circulating_get () / 1000;
}
if (rep_weight > min_rep_weight)
{
@ -1758,7 +1758,7 @@ void rai::gap_cache::vote (std::shared_ptr<rai::vote> vote_a)
rai::uint128_t rai::gap_cache::bootstrap_threshold (MDB_txn * transaction_a)
{
auto result ((node.ledger.supply (transaction_a) / 256) * node.config.bootstrap_fraction_numerator);
auto result ((node.ledger.supply.circulating_get () / 256) * node.config.bootstrap_fraction_numerator);
return result;
}
@ -1955,6 +1955,7 @@ void rai::node::start ()
ongoing_bootstrap ();
ongoing_store_flush ();
ongoing_rep_crawl ();
ongoing_supply_update ();
bootstrap.start ();
backup_wallet ();
active.announce_votes ();
@ -2050,6 +2051,18 @@ void rai::node::ongoing_keepalive ()
});
}
void rai::node::ongoing_supply_update ()
{
ledger.supply.circulating_update ();
std::weak_ptr<rai::node> node_w (shared_from_this ());
alarm.add (std::chrono::steady_clock::now () + std::chrono::minutes (5), [node_w]() {
if (auto node_l = node_w.lock ())
{
node_l->ongoing_supply_update ();
}
});
}
void rai::node::ongoing_rep_crawl ()
{
auto now (std::chrono::steady_clock::now ());
@ -2968,13 +2981,13 @@ void rai::election::broadcast_winner ()
rai::uint128_t rai::election::quorum_threshold (MDB_txn * transaction_a, rai::ledger & ledger_a)
{
// Threshold over which unanimous voting implies confirmation
return ledger_a.supply (transaction_a) / 2;
return ledger_a.supply.circulating_get () / 2;
}
rai::uint128_t rai::election::minimum_threshold (MDB_txn * transaction_a, rai::ledger & ledger_a)
{
// Minimum number of votes needed to change our ledger, under which we're probably disconnected
return ledger_a.supply (transaction_a) / 16;
return ledger_a.supply.circulating_get () / 16;
}
void rai::election::confirm_once (MDB_txn * transaction_a)
@ -3050,7 +3063,7 @@ bool rai::election::vote (std::shared_ptr<rai::vote> vote_a)
// see republish_vote documentation for an explanation of these rules
rai::transaction transaction (node.store.environment, nullptr, false);
auto replay (false);
auto supply (node.ledger.supply (transaction));
auto supply (node.ledger.supply.circulating_get ());
auto weight (node.ledger.weight (transaction, vote_a->account));
if (rai::rai_network == rai::rai_networks::rai_test_network || weight > supply / 1000) // 0.1% or above
{

View file

@ -543,6 +543,7 @@ public:
void ongoing_rep_crawl ();
void ongoing_bootstrap ();
void ongoing_store_flush ();
void ongoing_supply_update ();
void backup_wallet ();
int price (rai::uint128_t const &, int);
void generate_work (rai::block &);