Skip to content

Commit

Permalink
Improve account maintenance performance #803
Browse files Browse the repository at this point in the history
  • Loading branch information
abitmore committed Jun 23, 2018
1 parent eb13e71 commit b66e1ea
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 47 deletions.
5 changes: 4 additions & 1 deletion libraries/chain/account_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,10 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
obj.owner = o.owner;
obj.active = o.active;
obj.options = o.options;
obj.statistics = db().create<account_statistics_object>([&](account_statistics_object& s){s.owner = obj.id;}).id;
obj.statistics = db().create<account_statistics_object>([&obj](account_statistics_object& s){
s.owner = obj.id;
s.name = obj.name;
}).id;

if( o.extensions.value.owner_special_authority.valid() )
obj.owner_special_authority = *(o.extensions.value.owner_special_authority);
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/account_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ void account_balance_object::adjust_balance(const asset& delta)
{
assert(delta.asset_id == asset_type);
balance += delta.amount;
if( asset_type == asset_id_type() ) // CORE asset
maintenance_flag = true;
}

void account_statistics_object::process_fees(const account_object& a, database& d) const
Expand Down
6 changes: 6 additions & 0 deletions libraries/chain/db_balance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ void database::adjust_balance(account_id_type account, asset delta )
b.owner = account;
b.asset_type = delta.asset_id;
b.balance = delta.amount.value;
if( b.asset_type == asset_id_type() ) // CORE asset
b.maintenance_flag = true;
});
} else {
if( delta.amount < 0 )
Expand Down Expand Up @@ -158,6 +160,10 @@ void database::deposit_cashback(const account_object& acct, share_type amount, b
{
_acct.cashback_vb = *new_vbid;
} );
modify( acct.statistics( *this ), [&]( account_statistics_object& aso )
{
aso.has_cashback_vb = true;
} );
}

return;
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/db_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void database::debug_dump()
const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);

const auto& balance_index = db.get_index_type<account_balance_index>().indices();
const simple_index<account_statistics_object>& statistics_index = db.get_index_type<simple_index<account_statistics_object>>();
const auto& statistics_index = db.get_index_type<account_stats_index>().indices();
const auto& bids = db.get_index_type<collateral_bid_index>().indices();
const auto& settle_index = db.get_index_type<force_settlement_index>().indices();
map<asset_id_type,share_type> total_balances;
Expand Down
7 changes: 7 additions & 0 deletions libraries/chain/db_getter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,12 @@ uint32_t database::last_non_undoable_block_num() const
return head_block_num() - _undo_db.size();
}

const account_statistics_object& database::get_account_stats_by_owner( account_id_type owner )const
{
auto& idx = get_index_type<account_stats_index>().indices().get<by_owner>();
auto itr = idx.find( owner );
FC_ASSERT( itr != idx.end(), "Can not find account statistics object for owner ${a}", ("a",owner) );
return *itr;
}

} }
54 changes: 38 additions & 16 deletions libraries/chain/db_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ void database::initialize_indexes()
add_index< primary_index<asset_bitasset_data_index > >();
add_index< primary_index<simple_index<global_property_object >> >();
add_index< primary_index<simple_index<dynamic_global_property_object >> >();
add_index< primary_index<simple_index<account_statistics_object >> >();
add_index< primary_index<account_stats_index > >();
add_index< primary_index<simple_index<asset_dynamic_data_object >> >();
add_index< primary_index<simple_index<block_summary_object >> >();
add_index< primary_index<simple_index<chain_property_object > > >();
Expand Down Expand Up @@ -258,12 +258,19 @@ void database::init_genesis(const genesis_state_type& genesis_state)
n.owner.weight_threshold = 1;
n.active.weight_threshold = 1;
n.name = "committee-account";
n.statistics = create<account_statistics_object>( [&](account_statistics_object& s){ s.owner = n.id; }).id;
n.statistics = create<account_statistics_object>( [&n](account_statistics_object& s){
s.owner = n.id;
s.name = n.name;
s.core_in_balance = GRAPHENE_MAX_SHARE_SUPPLY;
}).id;
});
FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT);
FC_ASSERT(create<account_object>([this](account_object& a) {
a.name = "witness-account";
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 1;
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_WITNESS_ACCOUNT;
Expand All @@ -273,7 +280,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}).get_id() == GRAPHENE_WITNESS_ACCOUNT);
FC_ASSERT(create<account_object>([this](account_object& a) {
a.name = "relaxed-committee-account";
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 1;
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT;
Expand All @@ -283,7 +293,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}).get_id() == GRAPHENE_RELAXED_COMMITTEE_ACCOUNT);
FC_ASSERT(create<account_object>([this](account_object& a) {
a.name = "null-account";
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 1;
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
Expand All @@ -293,7 +306,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}).get_id() == GRAPHENE_NULL_ACCOUNT);
FC_ASSERT(create<account_object>([this](account_object& a) {
a.name = "temp-account";
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 0;
a.active.weight_threshold = 0;
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_TEMP_ACCOUNT;
Expand All @@ -303,7 +319,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
}).get_id() == GRAPHENE_TEMP_ACCOUNT);
FC_ASSERT(create<account_object>([this](account_object& a) {
a.name = "proxy-to-self";
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 1;
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
Expand All @@ -318,9 +337,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
uint64_t id = get_index<account_object>().get_next_id().instance();
if( id >= genesis_state.immutable_parameters.num_special_accounts )
break;
const account_object& acct = create<account_object>([&](account_object& a) {
const account_object& acct = create<account_object>([this,id](account_object& a) {
a.name = "special-account-" + std::to_string(id);
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
s.owner = a.id;
s.name = a.name;
}).id;
a.owner.weight_threshold = 1;
a.active.weight_threshold = 1;
a.registrar = a.lifetime_referrer = a.referrer = account_id_type(id);
Expand All @@ -334,11 +356,11 @@ void database::init_genesis(const genesis_state_type& genesis_state)

// Create core asset
const asset_dynamic_data_object& dyn_asset =
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
});
const asset_object& core_asset =
create<asset_object>( [&]( asset_object& a ) {
create<asset_object>( [&genesis_state,&dyn_asset]( asset_object& a ) {
a.symbol = GRAPHENE_SYMBOL;
a.options.max_supply = genesis_state.max_core_supply;
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
Expand All @@ -360,10 +382,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
if( id >= genesis_state.immutable_parameters.num_special_assets )
break;
const asset_dynamic_data_object& dyn_asset =
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
a.current_supply = 0;
});
const asset_object& asset_obj = create<asset_object>( [&]( asset_object& a ) {
const asset_object& asset_obj = create<asset_object>( [id,&dyn_asset]( asset_object& a ) {
a.symbol = "SPECIAL" + std::to_string( id );
a.options.max_supply = 0;
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
Expand Down Expand Up @@ -481,9 +503,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
cop.active = cop.owner;
account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get<object_id_type>();

modify( owner_account_id(*this).statistics(*this), [&]( account_statistics_object& o ) {
o.total_core_in_orders = collateral_rec.collateral;
});
modify( owner_account_id(*this).statistics(*this), [&collateral_rec]( account_statistics_object& o ) {
o.total_core_in_orders = collateral_rec.collateral;
});

create<call_order_object>([&](call_order_object& c) {
c.borrower = owner_account_id;
Expand Down
65 changes: 42 additions & 23 deletions libraries/chain/db_maint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,45 @@ vector<std::reference_wrapper<const typename Index::object_type>> database::sort
return refs;
}

template<class... Types>
void database::perform_account_maintenance(std::tuple<Types...> helpers)
template<class Type>
void database::perform_account_maintenance(Type tally_helper)
{
const auto& idx = get_index_type<account_index>().indices().get<by_name>();
for( const account_object& a : idx )
detail::for_each(helpers, a, detail::gen_seq<sizeof...(Types)>());
const auto& bal_idx = get_index_type< account_balance_index >().indices().get< by_maintenance_flag >();
if( bal_idx.begin() != bal_idx.end() )
{
auto bal_itr = bal_idx.rbegin();
while( bal_itr->maintenance_flag )
{
const account_balance_object& bal_obj = *bal_itr;

modify( get_account_stats_by_owner( bal_obj.owner ), [&bal_obj](account_statistics_object& aso) {
aso.core_in_balance = bal_obj.balance;
});

modify( bal_obj, []( account_balance_object& abo ) {
abo.maintenance_flag = false;
});

bal_itr = bal_idx.rbegin();
}
}

const auto& stats_idx = get_index_type< account_stats_index >().indices().get< by_maintenance_seq >();
auto stats_itr = stats_idx.lower_bound( true );

while( stats_itr != stats_idx.end() )
{
const account_statistics_object& acc_stat = *stats_itr;
const account_object& acc_obj = acc_stat.owner( *this );
++stats_itr;

if( acc_stat.has_some_core() )
tally_helper( acc_obj, acc_stat );

if( acc_stat.has_pending_fees() )
acc_stat.process_fees( acc_obj, *this );
}

}

/// @brief A visitor for @ref worker_type which calls pay_worker on the worker within
Expand Down Expand Up @@ -1014,7 +1047,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
d._total_voting_stake = 0;
}

void operator()(const account_object& stake_account) {
void operator()( const account_object& stake_account, const account_statistics_object& stats )
{
if( props.parameters.count_non_member_votes || stake_account.is_member(d.head_block_time()) )
{
// There may be a difference between the account whose stake is voting and the one specifying opinions.
Expand All @@ -1025,10 +1059,9 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
GRAPHENE_PROXY_TO_SELF_ACCOUNT)? stake_account
: d.get(stake_account.options.voting_account);

const auto& stats = stake_account.statistics(d);
uint64_t voting_stake = stats.total_core_in_orders.value
+ (stake_account.cashback_vb.valid() ? (*stake_account.cashback_vb)(d).balance.amount.value: 0)
+ d.get_balance(stake_account.get_id(), asset_id_type()).amount.value;
+ stats.core_in_balance.value;

for( vote_id_type id : opinion_account.options.votes )
{
Expand Down Expand Up @@ -1065,22 +1098,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
}
}
} tally_helper(*this, gpo);
struct process_fees_helper {
database& d;
const global_property_object& props;

process_fees_helper(database& d, const global_property_object& gpo)
: d(d), props(gpo) {}

void operator()(const account_object& a) {
a.statistics(d).process_fees(a, d);
}
} fee_helper(*this, gpo);

perform_account_maintenance(std::tie(
tally_helper,
fee_helper
));
perform_account_maintenance( tally_helper );

struct clear_canary {
clear_canary(vector<uint64_t>& target): target(target){}
Expand Down
Loading

0 comments on commit b66e1ea

Please sign in to comment.