Skip to content

Commit

Permalink
Merge pull request #90 from eosnetworkfoundation/enfs23_cc_configurab…
Browse files Browse the repository at this point in the history
…le_expired_accumulator_average_window

Configurable subjective account decay time
  • Loading branch information
ClaytonCalabrese authored Apr 14, 2022
2 parents abf96f9 + 5c4a1da commit 5f59702
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 9 deletions.
3 changes: 3 additions & 0 deletions docs/01_nodeos/03_plugins/producer_plugin/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ Config Options for eosio::producer_plugin:
transactions in any block before
returning to normal transaction
processing.
--subjective-account-decay-time-minutes (=1440)
Sets the time to return full subjective
cpu for accounts
--incoming-defer-ratio arg (=1) ratio between incoming transactions and
deferred transactions when both are
queued for execution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class subjective_billing {
uint64_t pending_cpu_us; // tracked cpu us for transactions that may still succeed in a block
decaying_accumulator expired_accumulator; // accumulator used to account for transactions that have expired

bool empty(uint32_t time_ordinal) {
bool empty(uint32_t time_ordinal, uint32_t expired_accumulator_average_window) {
return pending_cpu_us == 0 && expired_accumulator.value_at(time_ordinal, expired_accumulator_average_window) == 0;
}
};
Expand All @@ -61,6 +61,7 @@ class subjective_billing {
account_subjective_bill_cache _account_subjective_bill_cache;
block_subjective_bill_cache _block_subjective_bill_cache;
std::set<chain::account_name> _disabled_accounts;
uint32_t _expired_accumulator_average_window = config::account_cpu_usage_average_window_ms / subjective_time_interval_ms;

private:
uint32_t time_ordinal_for( const fc::time_point& t ) const {
Expand All @@ -75,15 +76,15 @@ class subjective_billing {
aitr->second.pending_cpu_us -= entry.subjective_cpu_bill;
EOS_ASSERT( aitr->second.pending_cpu_us >= 0, chain::tx_resource_exhaustion,
"Logic error in subjective account billing ${a}", ("a", entry.account) );
if( aitr->second.empty(time_ordinal) ) _account_subjective_bill_cache.erase( aitr );
if( aitr->second.empty(time_ordinal, _expired_accumulator_average_window) ) _account_subjective_bill_cache.erase( aitr );
}
}

void transition_to_expired( const trx_cache_entry& entry, uint32_t time_ordinal ) {
auto aitr = _account_subjective_bill_cache.find( entry.account );
if( aitr != _account_subjective_bill_cache.end() ) {
aitr->second.pending_cpu_us -= entry.subjective_cpu_bill;
aitr->second.expired_accumulator.add(entry.subjective_cpu_bill, time_ordinal, expired_accumulator_average_window);
aitr->second.expired_accumulator.add(entry.subjective_cpu_bill, time_ordinal, _expired_accumulator_average_window);
}
}

Expand All @@ -100,7 +101,6 @@ class subjective_billing {

public: // public for tests
static constexpr uint32_t subjective_time_interval_ms = 5'000;
static constexpr uint32_t expired_accumulator_average_window = config::account_cpu_usage_average_window_ms / subjective_time_interval_ms;

void remove_subjective_billing( const transaction_id_type& trx_id, uint32_t time_ordinal ) {
auto& idx = _trx_cache_index.get<by_id>();
Expand Down Expand Up @@ -141,7 +141,7 @@ class subjective_billing {
if( !_disabled && !_disabled_accounts.count( first_auth ) ) {
uint32_t bill = std::max<int64_t>( 0, elapsed.count() );
const auto time_ordinal = time_ordinal_for(now);
_account_subjective_bill_cache[first_auth].expired_accumulator.add(bill, time_ordinal, expired_accumulator_average_window);
_account_subjective_bill_cache[first_auth].expired_accumulator.add(bill, time_ordinal, _expired_accumulator_average_window);
}
}

Expand All @@ -161,7 +161,7 @@ class subjective_billing {

if (sub_bill_info) {
EOS_ASSERT(sub_bill_info->pending_cpu_us >= in_block_pending_cpu_us, chain::tx_resource_exhaustion, "Logic error subjective billing ${a}", ("a", first_auth) );
uint32_t sub_bill = sub_bill_info->pending_cpu_us - in_block_pending_cpu_us + sub_bill_info->expired_accumulator.value_at(time_ordinal, expired_accumulator_average_window );
uint32_t sub_bill = sub_bill_info->pending_cpu_us - in_block_pending_cpu_us + sub_bill_info->expired_accumulator.value_at(time_ordinal, _expired_accumulator_average_window );
return sub_bill;
} else {
return 0;
Expand Down Expand Up @@ -205,6 +205,15 @@ class subjective_billing {
}
return !exhausted;
}

uint32_t get_expired_accumulator_average_window() const {
return _expired_accumulator_average_window;
}

void set_expired_accumulator_average_window( fc::microseconds subjective_account_decay_time ) {
_expired_accumulator_average_window =
subjective_account_decay_time.count() / 1000 / subjective_time_interval_ms;
}
};

} //eosio
7 changes: 7 additions & 0 deletions plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,8 @@ void producer_plugin::set_program_options(
"Maximum wall-clock time, in milliseconds, spent retiring scheduled transactions in any block before returning to normal transaction processing.")
("subjective-cpu-leeway-us", boost::program_options::value<int32_t>()->default_value( config::default_subjective_cpu_leeway_us ),
"Time in microseconds allowed for a transaction that starts with insufficient CPU quota to complete and cover its CPU usage.")
("subjective-account-decay-time-minutes", bpo::value<uint32_t>()->default_value( config::account_cpu_usage_average_window_ms / 1000 / 60 ),
"Sets the time to return full subjective cpu for accounts")
("incoming-defer-ratio", bpo::value<double>()->default_value(1.0),
"ratio between incoming transactions and deferred transactions when both are queued for execution")
("incoming-transaction-queue-size-mb", bpo::value<uint16_t>()->default_value( 1024 ),
Expand Down Expand Up @@ -915,6 +917,11 @@ void producer_plugin::plugin_initialize(const boost::program_options::variables_
chain.set_subjective_cpu_leeway( fc::microseconds( options.at( "subjective-cpu-leeway-us" ).as<int32_t>() ) );
}

fc::microseconds subjective_account_decay_time = fc::minutes(options.at( "subjective-account-decay-time-minutes" ).as<uint32_t>());
EOS_ASSERT( subjective_account_decay_time.count() > 0, plugin_config_exception,
"subjective-account-decay-time-minutes ${dt} must be greater than 0", ("dt", subjective_account_decay_time.to_seconds() / 60));
my->_subjective_billing.set_expired_accumulator_average_window( subjective_account_decay_time );

my->_max_transaction_time_ms = options.at("max-transaction-time").as<int32_t>();

my->_max_irreversible_block_age_us = fc::seconds(options.at("max-irreversible-block-age").as<int32_t>());
Expand Down
7 changes: 4 additions & 3 deletions plugins/producer_plugin/test/test_subjective_billing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ BOOST_AUTO_TEST_CASE( subjective_bill_test ) {
account_name c = "c"_n;

const auto now = time_point::now();
const auto halftime = now + fc::milliseconds(subjective_billing::expired_accumulator_average_window * subjective_billing::subjective_time_interval_ms / 2);
const auto endtime = now + fc::milliseconds(subjective_billing::expired_accumulator_average_window * subjective_billing::subjective_time_interval_ms);

subjective_billing timing_sub_bill;
const auto halftime = now + fc::milliseconds(timing_sub_bill.get_expired_accumulator_average_window() * subjective_billing::subjective_time_interval_ms / 2);
const auto endtime = now + fc::milliseconds(timing_sub_bill.get_expired_accumulator_average_window() * subjective_billing::subjective_time_interval_ms);


{ // Failed transactions remain until expired in subjective billing.
Expand Down Expand Up @@ -129,7 +131,6 @@ BOOST_AUTO_TEST_CASE( subjective_bill_test ) {

{ // expired handling logic, full billing until expiration then failed/decay logic
subjective_billing sub_bill;
constexpr uint32_t window_size = subjective_billing::expired_accumulator_average_window;

sub_bill.subjective_bill( id1, now, a, fc::microseconds( 1024 ), false );
sub_bill.subjective_bill( id2, now + fc::microseconds(1), a, fc::microseconds( 1024 ), false );
Expand Down

0 comments on commit 5f59702

Please sign in to comment.