Skip to content

Commit e4dea46

Browse files
abitmorecogutvalera
authored andcommitted
Merge pull request bitshares#1085 from bitshares/803-maintenance-performance
Improve account maintenance performance bitshares#803
2 parents 27880b1 + 8f08ec9 commit e4dea46

13 files changed

+209
-67
lines changed

libraries/chain/account_evaluator.cpp

+34-14
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,15 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
188188
referrer_percent = GRAPHENE_100_PERCENT;
189189
}
190190

191-
const auto& new_acnt_object = db().create<account_object>( [&]( account_object& obj ){
191+
const auto& global_properties = d.get_global_properties();
192+
193+
const auto& new_acnt_object = d.create<account_object>( [&o,&d,&global_properties,referrer_percent]( account_object& obj )
194+
{
192195
obj.registrar = o.registrar;
193196
obj.referrer = o.referrer;
194-
obj.lifetime_referrer = o.referrer(db()).lifetime_referrer;
197+
obj.lifetime_referrer = o.referrer(d).lifetime_referrer;
195198

196-
auto& params = db().get_global_properties().parameters;
199+
const auto& params = global_properties.parameters;
197200
obj.network_fee_percentage = params.network_percent_of_fee;
198201
obj.lifetime_referrer_fee_percentage = params.lifetime_referrer_percent_of_fee;
199202
obj.referrer_rewards_percentage = referrer_percent;
@@ -202,7 +205,11 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
202205
obj.owner = o.owner;
203206
obj.active = o.active;
204207
obj.options = o.options;
205-
obj.statistics = db().create<account_statistics_object>([&](account_statistics_object& s){s.owner = obj.id;}).id;
208+
obj.statistics = d.create<account_statistics_object>([&obj](account_statistics_object& s){
209+
s.owner = obj.id;
210+
s.name = obj.name;
211+
s.is_voting = obj.options.is_voting();
212+
}).id;
206213

207214
if( o.extensions.value.owner_special_authority.valid() )
208215
obj.owner_special_authority = *(o.extensions.value.owner_special_authority);
@@ -226,17 +233,18 @@ object_id_type account_create_evaluator::do_apply( const account_create_operatio
226233
}
227234
*/
228235

229-
const auto& dynamic_properties = db().get_dynamic_global_properties();
230-
db().modify(dynamic_properties, [](dynamic_global_property_object& p) {
236+
const auto& dynamic_properties = d.get_dynamic_global_properties();
237+
d.modify(dynamic_properties, [](dynamic_global_property_object& p) {
231238
++p.accounts_registered_this_interval;
232239
});
233240

234-
const auto& global_properties = db().get_global_properties();
235-
if( dynamic_properties.accounts_registered_this_interval %
236-
global_properties.parameters.accounts_per_fee_scale == 0 )
237-
db().modify(global_properties, [](global_property_object& p) {
241+
if( dynamic_properties.accounts_registered_this_interval % global_properties.parameters.accounts_per_fee_scale == 0
242+
&& global_properties.parameters.account_fee_scale_bitshifts != 0 )
243+
{
244+
d.modify(global_properties, [](global_property_object& p) {
238245
p.parameters.current_fees->get<account_create_operation>().basic_fee <<= p.parameters.account_fee_scale_bitshifts;
239246
});
247+
}
240248

241249
if( o.extensions.value.owner_special_authority.valid()
242250
|| o.extensions.value.active_special_authority.valid() )
@@ -305,8 +313,20 @@ void_result account_update_evaluator::do_evaluate( const account_update_operatio
305313
void_result account_update_evaluator::do_apply( const account_update_operation& o )
306314
{ try {
307315
database& d = db();
308-
bool sa_before, sa_after;
309-
d.modify( *acnt, [&](account_object& a){
316+
317+
bool sa_before = acnt->has_special_authority();
318+
319+
// update account statistics
320+
if( o.new_options.valid() && o.new_options->is_voting() != acnt->options.is_voting() )
321+
{
322+
d.modify( acnt->statistics( d ), []( account_statistics_object& aso )
323+
{
324+
aso.is_voting = !aso.is_voting;
325+
} );
326+
}
327+
328+
// update account object
329+
d.modify( *acnt, [&o](account_object& a){
310330
if( o.owner )
311331
{
312332
a.owner = *o.owner;
@@ -318,7 +338,6 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
318338
a.top_n_control_flags = 0;
319339
}
320340
if( o.new_options ) a.options = *o.new_options;
321-
sa_before = a.has_special_authority();
322341
if( o.extensions.value.owner_special_authority.valid() )
323342
{
324343
a.owner_special_authority = *(o.extensions.value.owner_special_authority);
@@ -329,9 +348,10 @@ void_result account_update_evaluator::do_apply( const account_update_operation&
329348
a.active_special_authority = *(o.extensions.value.active_special_authority);
330349
a.top_n_control_flags = 0;
331350
}
332-
sa_after = a.has_special_authority();
333351
});
334352

353+
bool sa_after = acnt->has_special_authority();
354+
335355
if( sa_before && (!sa_after) )
336356
{
337357
const auto& sa_idx = d.get_index_type< special_authority_index >().indices().get<by_account>();

libraries/chain/account_object.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ void account_balance_object::adjust_balance(const asset& delta)
4646
{
4747
assert(delta.asset_id == asset_type);
4848
balance += delta.amount;
49+
if( asset_type == asset_id_type() ) // CORE asset
50+
maintenance_flag = true;
4951
}
5052

5153
void account_statistics_object::process_fees(const account_object& a, database& d) const

libraries/chain/db_balance.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ void database::adjust_balance(account_id_type account, asset delta )
6767
b.owner = account;
6868
b.asset_type = delta.asset_id;
6969
b.balance = delta.amount.value;
70+
if( b.asset_type == asset_id_type() ) // CORE asset
71+
b.maintenance_flag = true;
7072
});
7173
} else {
7274
if( delta.amount < 0 )
@@ -154,10 +156,14 @@ void database::deposit_cashback(const account_object& acct, share_type amount, b
154156

155157
if( new_vbid.valid() )
156158
{
157-
modify( acct, [&]( account_object& _acct )
159+
modify( acct, [&new_vbid]( account_object& _acct )
158160
{
159161
_acct.cashback_vb = *new_vbid;
160162
} );
163+
modify( acct.statistics( *this ), []( account_statistics_object& aso )
164+
{
165+
aso.has_cashback_vb = true;
166+
} );
161167
}
162168

163169
return;

libraries/chain/db_debug.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void database::debug_dump()
4343
const asset_dynamic_data_object& core_asset_data = db.get_core_asset().dynamic_asset_data_id(db);
4444

4545
const auto& balance_index = db.get_index_type<account_balance_index>().indices();
46-
const simple_index<account_statistics_object>& statistics_index = db.get_index_type<simple_index<account_statistics_object>>();
46+
const auto& statistics_index = db.get_index_type<account_stats_index>().indices();
4747
const auto& bids = db.get_index_type<collateral_bid_index>().indices();
4848
const auto& settle_index = db.get_index_type<force_settlement_index>().indices();
4949
map<asset_id_type,share_type> total_balances;

libraries/chain/db_getter.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,12 @@ uint32_t database::last_non_undoable_block_num() const
9797
return head_block_num() - _undo_db.size();
9898
}
9999

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

101108
} }

libraries/chain/db_init.cpp

+38-16
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ void database::initialize_indexes()
209209
add_index< primary_index<asset_bitasset_data_index > >();
210210
add_index< primary_index<simple_index<global_property_object >> >();
211211
add_index< primary_index<simple_index<dynamic_global_property_object >> >();
212-
add_index< primary_index<simple_index<account_statistics_object >> >();
212+
add_index< primary_index<account_stats_index > >();
213213
add_index< primary_index<simple_index<asset_dynamic_data_object >> >();
214214
add_index< primary_index<simple_index<block_summary_object >> >();
215215
add_index< primary_index<simple_index<chain_property_object > > >();
@@ -258,12 +258,19 @@ void database::init_genesis(const genesis_state_type& genesis_state)
258258
n.owner.weight_threshold = 1;
259259
n.active.weight_threshold = 1;
260260
n.name = "committee-account";
261-
n.statistics = create<account_statistics_object>( [&](account_statistics_object& s){ s.owner = n.id; }).id;
261+
n.statistics = create<account_statistics_object>( [&n](account_statistics_object& s){
262+
s.owner = n.id;
263+
s.name = n.name;
264+
s.core_in_balance = GRAPHENE_MAX_SHARE_SUPPLY;
265+
}).id;
262266
});
263267
FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT);
264268
FC_ASSERT(create<account_object>([this](account_object& a) {
265269
a.name = "witness-account";
266-
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
270+
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
271+
s.owner = a.id;
272+
s.name = a.name;
273+
}).id;
267274
a.owner.weight_threshold = 1;
268275
a.active.weight_threshold = 1;
269276
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_WITNESS_ACCOUNT;
@@ -273,7 +280,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
273280
}).get_id() == GRAPHENE_WITNESS_ACCOUNT);
274281
FC_ASSERT(create<account_object>([this](account_object& a) {
275282
a.name = "relaxed-committee-account";
276-
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
283+
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
284+
s.owner = a.id;
285+
s.name = a.name;
286+
}).id;
277287
a.owner.weight_threshold = 1;
278288
a.active.weight_threshold = 1;
279289
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT;
@@ -283,7 +293,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
283293
}).get_id() == GRAPHENE_RELAXED_COMMITTEE_ACCOUNT);
284294
FC_ASSERT(create<account_object>([this](account_object& a) {
285295
a.name = "null-account";
286-
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
296+
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
297+
s.owner = a.id;
298+
s.name = a.name;
299+
}).id;
287300
a.owner.weight_threshold = 1;
288301
a.active.weight_threshold = 1;
289302
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
@@ -293,7 +306,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
293306
}).get_id() == GRAPHENE_NULL_ACCOUNT);
294307
FC_ASSERT(create<account_object>([this](account_object& a) {
295308
a.name = "temp-account";
296-
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
309+
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
310+
s.owner = a.id;
311+
s.name = a.name;
312+
}).id;
297313
a.owner.weight_threshold = 0;
298314
a.active.weight_threshold = 0;
299315
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_TEMP_ACCOUNT;
@@ -303,7 +319,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
303319
}).get_id() == GRAPHENE_TEMP_ACCOUNT);
304320
FC_ASSERT(create<account_object>([this](account_object& a) {
305321
a.name = "proxy-to-self";
306-
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
322+
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
323+
s.owner = a.id;
324+
s.name = a.name;
325+
}).id;
307326
a.owner.weight_threshold = 1;
308327
a.active.weight_threshold = 1;
309328
a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
@@ -318,9 +337,12 @@ void database::init_genesis(const genesis_state_type& genesis_state)
318337
uint64_t id = get_index<account_object>().get_next_id().instance();
319338
if( id >= genesis_state.immutable_parameters.num_special_accounts )
320339
break;
321-
const account_object& acct = create<account_object>([&](account_object& a) {
340+
const account_object& acct = create<account_object>([this,id](account_object& a) {
322341
a.name = "special-account-" + std::to_string(id);
323-
a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
342+
a.statistics = create<account_statistics_object>([&a](account_statistics_object& s){
343+
s.owner = a.id;
344+
s.name = a.name;
345+
}).id;
324346
a.owner.weight_threshold = 1;
325347
a.active.weight_threshold = 1;
326348
a.registrar = a.lifetime_referrer = a.referrer = account_id_type(id);
@@ -334,11 +356,11 @@ void database::init_genesis(const genesis_state_type& genesis_state)
334356

335357
// Create core asset
336358
const asset_dynamic_data_object& dyn_asset =
337-
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
359+
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
338360
a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
339361
});
340362
const asset_object& core_asset =
341-
create<asset_object>( [&]( asset_object& a ) {
363+
create<asset_object>( [&genesis_state,&dyn_asset]( asset_object& a ) {
342364
a.symbol = GRAPHENE_SYMBOL;
343365
a.options.max_supply = genesis_state.max_core_supply;
344366
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
@@ -360,10 +382,10 @@ void database::init_genesis(const genesis_state_type& genesis_state)
360382
if( id >= genesis_state.immutable_parameters.num_special_assets )
361383
break;
362384
const asset_dynamic_data_object& dyn_asset =
363-
create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
385+
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
364386
a.current_supply = 0;
365387
});
366-
const asset_object& asset_obj = create<asset_object>( [&]( asset_object& a ) {
388+
const asset_object& asset_obj = create<asset_object>( [id,&dyn_asset]( asset_object& a ) {
367389
a.symbol = "SPECIAL" + std::to_string( id );
368390
a.options.max_supply = 0;
369391
a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
@@ -481,9 +503,9 @@ void database::init_genesis(const genesis_state_type& genesis_state)
481503
cop.active = cop.owner;
482504
account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get<object_id_type>();
483505

484-
modify( owner_account_id(*this).statistics(*this), [&]( account_statistics_object& o ) {
485-
o.total_core_in_orders = collateral_rec.collateral;
486-
});
506+
modify( owner_account_id(*this).statistics(*this), [&collateral_rec]( account_statistics_object& o ) {
507+
o.total_core_in_orders = collateral_rec.collateral;
508+
});
487509

488510
create<call_order_object>([&](call_order_object& c) {
489511
c.borrower = owner_account_id;

libraries/chain/db_maint.cpp

+42-23
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,45 @@ vector<std::reference_wrapper<const typename Index::object_type>> database::sort
7272
return refs;
7373
}
7474

75-
template<class... Types>
76-
void database::perform_account_maintenance(std::tuple<Types...> helpers)
75+
template<class Type>
76+
void database::perform_account_maintenance(Type tally_helper)
7777
{
78-
const auto& idx = get_index_type<account_index>().indices().get<by_name>();
79-
for( const account_object& a : idx )
80-
detail::for_each(helpers, a, detail::gen_seq<sizeof...(Types)>());
78+
const auto& bal_idx = get_index_type< account_balance_index >().indices().get< by_maintenance_flag >();
79+
if( bal_idx.begin() != bal_idx.end() )
80+
{
81+
auto bal_itr = bal_idx.rbegin();
82+
while( bal_itr->maintenance_flag )
83+
{
84+
const account_balance_object& bal_obj = *bal_itr;
85+
86+
modify( get_account_stats_by_owner( bal_obj.owner ), [&bal_obj](account_statistics_object& aso) {
87+
aso.core_in_balance = bal_obj.balance;
88+
});
89+
90+
modify( bal_obj, []( account_balance_object& abo ) {
91+
abo.maintenance_flag = false;
92+
});
93+
94+
bal_itr = bal_idx.rbegin();
95+
}
96+
}
97+
98+
const auto& stats_idx = get_index_type< account_stats_index >().indices().get< by_maintenance_seq >();
99+
auto stats_itr = stats_idx.lower_bound( true );
100+
101+
while( stats_itr != stats_idx.end() )
102+
{
103+
const account_statistics_object& acc_stat = *stats_itr;
104+
const account_object& acc_obj = acc_stat.owner( *this );
105+
++stats_itr;
106+
107+
if( acc_stat.has_some_core_voting() )
108+
tally_helper( acc_obj, acc_stat );
109+
110+
if( acc_stat.has_pending_fees() )
111+
acc_stat.process_fees( acc_obj, *this );
112+
}
113+
81114
}
82115

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

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

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

10331066
for( vote_id_type id : opinion_account.options.votes )
10341067
{
@@ -1065,22 +1098,8 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
10651098
}
10661099
}
10671100
} tally_helper(*this, gpo);
1068-
struct process_fees_helper {
1069-
database& d;
1070-
const global_property_object& props;
1071-
1072-
process_fees_helper(database& d, const global_property_object& gpo)
1073-
: d(d), props(gpo) {}
1074-
1075-
void operator()(const account_object& a) {
1076-
a.statistics(d).process_fees(a, d);
1077-
}
1078-
} fee_helper(*this, gpo);
10791101

1080-
perform_account_maintenance(std::tie(
1081-
tally_helper,
1082-
fee_helper
1083-
));
1102+
perform_account_maintenance( tally_helper );
10841103

10851104
struct clear_canary {
10861105
clear_canary(vector<uint64_t>& target): target(target){}

0 commit comments

Comments
 (0)