all: distinguish *_ops_* from *_amount_* at limiter

This commit is contained in:
Thomas Schoebel-Theuer 2016-01-19 09:15:44 +01:00 committed by Thomas Schoebel-Theuer
parent b5209337a9
commit 628c636dff
8 changed files with 109 additions and 47 deletions

View File

@ -61,8 +61,10 @@ int mars_limit(struct mars_limiter *lim, int amount)
* They will intentionally wrap around.
* Userspace must take care of that.
*/
lim->lim_total_ops++;
lim->lim_total_sum += amount;
if (likely(amount > 0)) {
lim->lim_total_amount += amount;
lim->lim_total_ops++;
}
/* Only use incremental accumulation at repeated calls, but
* never after longer pauses.
@ -71,26 +73,48 @@ int mars_limit(struct mars_limiter *lim, int amount)
window < (long long)lim->lim_max_window * (LIMITER_TIME_RESOLUTION / 1000))) {
long long rate_raw;
int rate;
int max_rate;
/* Races are possible, but taken into account.
* There is no real harm from rarely lost updates.
*/
if (likely(amount > 0)) {
lim->lim_accu += amount;
lim->lim_cumul += amount;
lim->lim_count++;
lim->lim_amount_accu += amount;
lim->lim_amount_cumul += amount;
lim->lim_ops_accu++;
lim->lim_ops_cumul++;
}
rate_raw = lim->lim_accu * LIMITER_TIME_RESOLUTION / window;
/* compute amount values */
rate_raw = lim->lim_amount_accu * LIMITER_TIME_RESOLUTION / window;
rate = rate_raw;
if (unlikely(rate_raw > INT_MAX)) {
rate = INT_MAX;
}
lim->lim_rate = rate;
lim->lim_amount_rate = rate;
// limit exceeded?
if (lim->lim_max_rate > 0 && rate > lim->lim_max_rate) {
int this_delay = (window * rate / lim->lim_max_rate - window) / (LIMITER_TIME_RESOLUTION / 1000);
/* amount limit exceeded? */
max_rate = lim->lim_max_amount_rate;
if (max_rate > 0 && rate > max_rate) {
int this_delay = (window * rate / max_rate - window) / (LIMITER_TIME_RESOLUTION / 1000);
// compute maximum
if (this_delay > delay && this_delay > 0)
delay = this_delay;
}
/* compute ops values */
rate_raw = lim->lim_ops_accu * LIMITER_TIME_RESOLUTION / window;
rate = rate_raw;
if (unlikely(rate_raw > INT_MAX)) {
rate = INT_MAX;
}
lim->lim_ops_rate = rate;
/* ops limit exceeded? */
max_rate = lim->lim_max_ops_rate;
if (max_rate > 0 && rate > max_rate) {
int this_delay = (window * rate / max_rate - window) / (LIMITER_TIME_RESOLUTION / 1000);
// compute maximum
if (this_delay > delay && this_delay > 0)
delay = this_delay;
@ -100,30 +124,41 @@ int mars_limit(struct mars_limiter *lim, int amount)
*/
window -= lim->lim_min_window * (LIMITER_TIME_RESOLUTION / 1000);
if (window > 0) {
long long used_up = (long long)lim->lim_rate * window / LIMITER_TIME_RESOLUTION;
long long used_up = (long long)lim->lim_amount_rate * window / LIMITER_TIME_RESOLUTION;
if (used_up > 0) {
lamport_time_add_ns(&lim->lim_stamp, window);
lim->lim_accu -= used_up;
if (unlikely(lim->lim_accu < 0))
lim->lim_accu = 0;
lim->lim_amount_accu -= used_up;
if (unlikely(lim->lim_amount_accu < 0))
lim->lim_amount_accu = 0;
}
used_up = (long long)lim->lim_ops_rate * window / LIMITER_TIME_RESOLUTION;
if (used_up > 0) {
lamport_time_add_ns(&lim->lim_stamp, window);
lim->lim_ops_accu -= used_up;
if (unlikely(lim->lim_ops_accu < 0))
lim->lim_ops_accu = 0;
}
}
} else { // reset, start over with new measurement cycle
struct lamport_time sub = ns_to_lamport_time(lim->lim_min_window * (LIMITER_TIME_RESOLUTION / 1000));
if (unlikely(amount < 0))
amount = 0;
lim->lim_ops_accu = 1;
lim->lim_amount_accu = amount;
lim->lim_stamp = lamport_time_sub(now, sub);
lim->lim_accu = amount;
lim->lim_rate = 0;
lim->lim_ops_rate = 0;
lim->lim_amount_rate = 0;
}
lim = lim->lim_father;
}
return delay;
}
EXPORT_SYMBOL_GPL(mars_limit);
void mars_limit_sleep(struct mars_limiter *lim, int amount)
{
int sleep = mars_limit(lim, amount);
if (sleep > 0) {
if (unlikely(lim->lim_max_delay <= 0))
lim->lim_max_delay = 1000;
@ -132,7 +167,6 @@ void mars_limit_sleep(struct mars_limiter *lim, int amount)
brick_msleep(sleep);
}
}
EXPORT_SYMBOL_GPL(mars_limit_sleep);
void mars_limit_reset(struct mars_limiter *lim)
{

View File

@ -33,19 +33,22 @@ struct mars_limiter {
/* hierarchy tree */
struct mars_limiter *lim_father;
/* tunables */
int lim_max_rate;
int lim_max_ops_rate;
int lim_max_amount_rate;
int lim_max_delay;
int lim_min_window;
int lim_max_window;
/* readable */
int lim_rate;
int lim_cumul;
int lim_count;
int lim_ops_rate;
int lim_amount_rate;
int lim_ops_cumul;
int lim_amount_cumul;
int lim_total_ops;
int lim_total_sum;
int lim_total_amount;
struct lamport_time lim_stamp;
/* internal */
long long lim_accu;
long long lim_ops_accu;
long long lim_amount_accu;
};
extern int mars_limit(struct mars_limiter *lim, int amount);

View File

@ -1161,7 +1161,7 @@ EXPORT_SYMBOL_GPL(client_brick_type);
////////////////// module init stuff /////////////////////////
struct mars_limiter client_limiter = {
.lim_max_rate = 0,
/* Let all be zero */
};
EXPORT_SYMBOL_GPL(client_limiter);

View File

@ -78,7 +78,7 @@ int if_throttle_start_size = 0; // in kb
EXPORT_SYMBOL_GPL(if_throttle_start_size);
struct mars_limiter if_throttle = {
.lim_max_rate = 10000,
.lim_max_amount_rate = 10000,
};
///////////////////////// own type definitions ////////////////////////

View File

@ -936,7 +936,7 @@ static int _server_thread(void *data)
////////////////// module init stuff /////////////////////////
struct mars_limiter server_limiter = {
.lim_max_rate = 0,
/* Let all be zero */
};
EXPORT_SYMBOL_GPL(server_limiter);

View File

@ -1606,10 +1606,19 @@ void _show_status_all(struct mars_global *global)
}
static
void _show_rate(struct mars_rotate *rot, struct mars_limiter *limiter, const char *name)
void _show_rate(struct mars_rotate *rot, struct mars_limiter *limiter, const char *basename)
{
char *name;
mars_limit(limiter, 0);
__show_actual(rot->parent_path, name, limiter->lim_rate);
name = path_make("ops-%s", basename);
__show_actual(rot->parent_path, name, limiter->lim_ops_rate);
brick_string_free(name);
name = path_make("amount-%s", basename);
__show_actual(rot->parent_path, name, limiter->lim_amount_rate);
brick_string_free(name);
}
///////////////////////////////////////////////////////////////////////
@ -1758,7 +1767,8 @@ int __make_copy(
"from = '%s' to = '%s'"
" on = %d start_pos = %lld end_pos = %lld"
" actual_pos = %lld actual_stamp = %ld.%09ld"
" rate = %d read_fly = %d write_fly = %d error_code = %d nr_errors = %d",
" ops_rate = %d amount_rate = %d"
" read_fly = %d write_fly = %d error_code = %d nr_errors = %d",
argv[0],
argv[1],
_copy->power.led_on,
@ -1766,7 +1776,8 @@ int __make_copy(
_copy->copy_end,
_copy->copy_last,
_copy->copy_last_stamp.tv_sec, _copy->copy_last_stamp.tv_nsec,
_copy->copy_limiter ? _copy->copy_limiter->lim_rate : 0,
_copy->copy_limiter ? _copy->copy_limiter->lim_ops_rate : 0,
_copy->copy_limiter ? _copy->copy_limiter->lim_amount_rate : 0,
atomic_read(&_copy->copy_read_flight),
atomic_read(&_copy->copy_write_flight),
_copy->copy_error,

View File

@ -240,15 +240,17 @@ done:
VEC_ENTRY(NAME, VAR, MODE, 1)
#define LIMITER_ENTRIES(VAR, PREFIX, SUFFIX) \
INT_ENTRY(PREFIX "_total_ops_" SUFFIX, (VAR)->lim_total_ops, 0400), \
INT_ENTRY(PREFIX "_total_sum_" SUFFIX, (VAR)->lim_total_sum, 0400), \
INT_ENTRY(PREFIX "_ratelimit_" SUFFIX, (VAR)->lim_max_rate, 0600), \
INT_ENTRY(PREFIX "_total_ops", (VAR)->lim_total_ops, 0400), \
INT_ENTRY(PREFIX "_total_" SUFFIX, (VAR)->lim_total_amount, 0400), \
INT_ENTRY(PREFIX "_ratelimit_ops", (VAR)->lim_max_ops_rate, 0600), \
INT_ENTRY(PREFIX "_ratelimit_" SUFFIX, (VAR)->lim_max_amount_rate, 0600), \
INT_ENTRY(PREFIX "_maxdelay_ms", (VAR)->lim_max_delay,0600), \
INT_ENTRY(PREFIX "_minwindow_ms", (VAR)->lim_min_window,0600), \
INT_ENTRY(PREFIX "_maxwindow_ms", (VAR)->lim_max_window,0600), \
INT_ENTRY(PREFIX "_cumul_" SUFFIX, (VAR)->lim_cumul, 0600), \
INT_ENTRY(PREFIX "_count_ops", (VAR)->lim_count, 0600), \
INT_ENTRY(PREFIX "_rate_" SUFFIX, (VAR)->lim_rate, 0400) \
INT_ENTRY(PREFIX "_cumul_ops", (VAR)->lim_ops_cumul, 0600), \
INT_ENTRY(PREFIX "_cumul_" SUFFIX, (VAR)->lim_amount_cumul, 0600), \
INT_ENTRY(PREFIX "_rate_ops", (VAR)->lim_ops_rate, 0400), \
INT_ENTRY(PREFIX "_rate_" SUFFIX, (VAR)->lim_amount_rate, 0400) \
#define THRESHOLD_ENTRIES(VAR, PREFIX) \
INT_ENTRY(PREFIX "_threshold_us", (VAR)->thr_limit, 0600), \

View File

@ -5418,7 +5418,7 @@ sub eval_fn {
my $lnk = $$env{"resdir"} . "/actual-" . $$env{"host"} . "/replay-code";
return get_link($lnk, 2);
}
if (/^(sync|fetch|replay|work)[-_]?(rate|remain)$/) {
if (/^(sync|fetch|replay|work)[-_]?(rate|ops[-_]?rate|amount[-_]?rate|remain)$/) {
my $what = $1;
my $select = $2;
if ($what eq "work") {
@ -5433,22 +5433,34 @@ sub eval_fn {
return $val1 if $val1 > $val2;
return $val2;
}
my $name = $select;
$name = "amount_rate" if ($name eq "rate" || $name eq "remain");
$name =~ s/-/_/;
my %names =
(
"sync" => "sync_rate",
"fetch" => "file_rate",
"replay" => "replay_rate",
"sync" => "sync",
"fetch" => "file",
"replay" => "replay",
);
my $lnk = $$env{"resdir"} . "/actual-" . $$env{"host"} . "/" . $names{$what};
$name =~ s/_/-$names{$what}_/;
my $lnk = $$env{"resdir"} . "/actual-" . $$env{"host"} . "/$name";
my $rate = get_link($lnk, 2);
return "" if !defined($rate) || $rate eq "" || $rate < 0;
return $rate * 1024 if $select eq "rate";
# deprecated: compatibility with old version
if (!defined($rate) || $rate eq "") {
$lnk =~ s:/amount-:/:;
$rate = get_link($lnk, 2);
}
if ($select eq "remain") {
my $rest = make_numeric(eval_fn($env, "$what-rest", ""));
return 0 if $rest <= 0;
return -1 if ($rate <= 0);
return -1 if (!defined($rate) || $rate eq "" || $rate <= 0);
return $rest / 1024 / $rate;
}
if ($select =~ /rate/) {
return 0 if (!defined($rate) || !$rate || $rate <= 0);
return $rate if $select =~ /^ops-/;
return $rate * 1024;
}
ldie "unknown macro $_\n";
}
if (/^sync[-_]?size$/) {
@ -6431,7 +6443,7 @@ my %trivial_globs =
=> "",
"writeback-rest"
=> "",
"{sync,fetch,replay}-{rate,remain}"
"{sync,fetch,replay}-{ops-rate,amount-rate,rate,remain}"
=> "",
"replay-basenr"
=> "",