提交 40b5e618 编写于 作者: B Bart Wyatt

interim checkin

上级 7f269dd1
......@@ -1683,10 +1683,9 @@ void chain_controller::update_usage( transaction_metadata& meta, uint32_t act_us
}
}
_db.modify( dgpo, [&]( auto& props ) {
props.average_block_acts.add_usage( act_usage, head_time );
_db.modify( state, [&]( rate_limiting_state_object& rls ) {
rls.average_block_cpu_usage.add_usage( cpu_usage, head_time );
});
}
const apply_handler* chain_controller::find_apply_handler( account_name receiver, account_name scope, action_name act ) const
......
......@@ -2,38 +2,4 @@
namespace eosio { namespace chain {
void dynamic_global_property_object::update_virtual_net_bandwidth( const chain_config& cfg ) {
if( average_block_size.average()> (cfg.target_block_size * config::rate_limiting_precision) ) {
virtual_net_bandwidth *= 99;
virtual_net_bandwidth /= 100;
wlog( "reducing virtual net bandwidth by 1%, ${vnb}", ("vnb", virtual_net_bandwidth) );
wdump((average_block_size.average())(cfg.target_block_size*config::rate_limiting_precision));
} else {
virtual_net_bandwidth *= 1000;
virtual_net_bandwidth /= 999;
// ilog( "increasing virtual net bandwidth by .1%, ${vnb}", ("vnb", virtual_net_bandwidth) );
}
auto min = (cfg.max_block_size * config::blocksize_average_window_ms) / config::block_interval_ms;
if( virtual_net_bandwidth < min ) virtual_net_bandwidth = min;
if( virtual_net_bandwidth > min * 1000 ) virtual_net_bandwidth = min * 1000;
}
void dynamic_global_property_object::update_virtual_act_bandwidth( const chain_config& cfg ) {
if( average_block_acts.average() > (cfg.target_block_acts * config::rate_limiting_precision) ) {
virtual_act_bandwidth *= 99;
virtual_act_bandwidth /= 100;
} else {
virtual_act_bandwidth *= 1000;
virtual_act_bandwidth /= 999;
}
auto min = (cfg.max_block_acts * config::blocksize_average_window_ms) / config::block_interval_ms;
if( virtual_act_bandwidth < min ) virtual_act_bandwidth = min;
if( virtual_act_bandwidth > min * 1000 ) virtual_act_bandwidth = min * 1000;
}
} } /// eosio::chain
......@@ -7,38 +7,57 @@
namespace eosio { namespace chain {
template<typename T>
struct ratio {
T numerator;
T denominator;
};
template<typename T>
ratio<T> make_ratio(T n, T d) {
return ratio<T>{n, d};
}
template<typename T>
T operator* (T value, const ratio<T>& r) {
return (value * r.numerator) / r.denominator;
}
/**
* This class accumulates an average value taking periodic inputs.
*
* The average value returns to 0 after WindowMS without any updates and
* decays linerally if updates occur in the middle of a window before adding
* the new value.
*
* The value stored is Precision times the sum of the inputs.
*/
template<uint32_t WindowMs, uint64_t Precision = config::rate_limiting_precision>
template<uint64_t Precision = config::rate_limiting_precision>
struct average_accumulator
{
time_point last_update;
uint64_t value = 0;
average_accumulator(uint32_t window_blocks)
: window_blocks(window_blocks)
, last_head_block_num()
, value(0)
{
}
uint32_t window_blocks;
uint32_t last_head_block_num;
uint64_t value;
/**
* return the average value in rate_limiting_precision
*/
uint64_t average()const { return value / WindowMs; }
uint64_t average()const { return value / window_blocks; }
void add_usage( uint64_t units, time_point now )
void add_usage( uint64_t units, uint32_t head_block_num )
{
if( now != last_update ) {
auto elapsed = now - last_update;
if( elapsed > fc::milliseconds(WindowMs) ) {
value = 0;
} else if( elapsed > fc::days(0) ) {
value *= (fc::milliseconds(WindowMs) - elapsed).count();
value /= fc::milliseconds(WindowMs).count();
}
last_update = now;
if( head_block_num != last_head_block_num ) {
const auto decay = make_ratio(
(uint64_t) window_blocks - 1,
(uint64_t) window_blocks
);
value = value * decay;
}
value += units * Precision;
}
};
......@@ -94,6 +113,29 @@ namespace eosio { namespace chain {
>
>;
struct elastic_limit_parameters {
uint64_t target; // the desired usage
uint64_t max; // the maximum usage
uint32_t periods; // the number of aggregation periods that contribute to the average usage
uint32_t max_multiplier; // the multiplier by which virtual space can oversell usage when uncongested
ratio contract_rate; // the rate at which a congested resource contracts its limit
ratio expand_rate; // the rate at which an uncongested resource expands its limits
};
class resource_limits_config_object : public chainbase::object<resource_limits_config_object_type, resource_limits_config_object> {
OBJECT_CTOR(resource_limits_config_object);
id_type id;
uint32_t base_per_transaction_net_usage;
uint32_t base_per_transaction_cpu_usage;
uint32_t per_signature_cpu_usage;
elastic_limit_parameters cpu_limit_parameters;
elastic_limit_parameters net_limit_parameters;
};
class resource_limits_state_object : public chainbase::object<resource_limits_state_object_type, resource_limits_state_object> {
OBJECT_CTOR(resource_limits_state_object);
......@@ -101,16 +143,16 @@ namespace eosio { namespace chain {
* Track the average blocksize over the past 60 seconds and use it to adjust the
* reserve ratio for bandwidth rate limiting calclations.
*/
average_accumulator<config::blocksize_average_window_ms> average_block_size;
average_accumulator<config::blocksize_average_window_ms> average_block_net_usage;
/**
* Track the average actions per block over the past 60 seconds and use it to
* adjust hte reserve ration for action rate limiting calculations
*/
average_accumulator<config::blocksize_average_window_ms> average_block_acts;
average_accumulator<config::blocksize_average_window_ms> average_block_cpu_usage;
void update_virtual_net_bandwidth( const chain_config& cfg );
void update_virtual_act_bandwidth( const chain_config& cfg );
void update_virtual_net_limit( const resource_limits_config_object& cfg );
void update_virtual_cpu_limit( const resource_limits_config_object& cfg );
uint64_t total_net_weight = 0;
uint64_t total_cpu_weight = 0;
......@@ -146,16 +188,6 @@ namespace eosio { namespace chain {
};
class resource_limits_config_object : public chainbase::object<resource_limits_config_object_type, resource_limits_config_object> {
OBJECT_CTOR(resource_limits_config_object);
id_type id;
uint32_t base_per_transaction_net_usage;
uint32_t base_per_transaction_cpu_usage;
uint32_t per_signature_cpu_usage;
};
using resource_limits_config_index = chainbase::shared_multi_index_container<
resource_limits_config_object,
indexed_by<
......
#include <eosio/chain/rate_limiting.hpp>
#include <algorithm>
namespace eosio { namespace chain {
static uint64_t update_elastic_limit(uint64_t current_limit, uint64_t average_usage_ex, const elastic_limit_parameters& params) {
uint64_t result = current_limit;
if (average_usage_ex > (params.target * config::rate_limiting_precision) ) {
result = result * params.contract_rate;
} else {
result = result * params.expand_rate;
}
uint64_t min = params.max * params.periods;
return std::min(std::max(result, min), min * params.max_multiplier));
}
void resource_limits_state_object::update_virtual_cpu_limit( const resource_limits_config_object& cfg ) {
virtual_cpu_limit = update_elastic_limit(virtual_cpu_limit, average_block_cpu_usage.average(), cfg.cpu_limit_parameters);
}
void resource_limits_state_object::update_virtual_net_limit( const resource_limits_config_object& cfg ) {
virtual_net_limit = update_elastic_limit(virtual_net_limit, average_block_net_usage.average(), cfg.net_limit_parameters);
}
} } /// eosio::chain
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册