mirror of
https://github.com/schoebel/mars
synced 2024-12-23 23:23:09 +00:00
limiter: introduce hierarchy, always show current rate
This commit is contained in:
parent
84ca56f6b1
commit
09e7732342
@ -7,36 +7,49 @@
|
||||
|
||||
int mars_limit(struct mars_limiter *lim, int amount)
|
||||
{
|
||||
int res = 0;
|
||||
int delay = 0;
|
||||
unsigned long long now;
|
||||
|
||||
now = cpu_clock(raw_smp_processor_id());
|
||||
|
||||
if (lim->lim_max_rate > 0 && likely(lim->lim_stamp)) {
|
||||
long long elapsed = now - lim->lim_stamp;
|
||||
long long rate;
|
||||
|
||||
/* Races are possible, but taken into account.
|
||||
* There is no real harm from rarely lost updates.
|
||||
*/
|
||||
lim->lim_accu += amount;
|
||||
|
||||
rate = (long long)lim->lim_accu * LIMITER_TIME_RESOLUTION / elapsed;
|
||||
|
||||
if (rate > lim->lim_max_rate) {
|
||||
res = 1001 - lim->lim_max_rate * 1000 / rate;
|
||||
/* Compute the maximum delay along the path
|
||||
* down to the root of the hierarchy tree.
|
||||
*/
|
||||
while (lim != NULL) {
|
||||
if (likely(lim->lim_stamp)) {
|
||||
long long elapsed = now - lim->lim_stamp;
|
||||
int rate;
|
||||
|
||||
/* Races are possible, but taken into account.
|
||||
* There is no real harm from rarely lost updates.
|
||||
*/
|
||||
lim->lim_accu += amount;
|
||||
|
||||
rate = (long long)lim->lim_accu * LIMITER_TIME_RESOLUTION / elapsed;
|
||||
lim->lim_rate = rate;
|
||||
|
||||
// limit exceeded?
|
||||
if (lim->lim_max_rate > 0 && rate > lim->lim_max_rate) {
|
||||
int this_delay = 1001 - lim->lim_max_rate * 1000 / rate;
|
||||
// compute maximum
|
||||
if (!delay || this_delay > delay)
|
||||
delay = this_delay;
|
||||
}
|
||||
|
||||
elapsed -= LIMITER_TIME_RESOLUTION * 2;
|
||||
if (elapsed > LIMITER_TIME_RESOLUTION) {
|
||||
lim->lim_stamp += elapsed;
|
||||
if (lim->lim_accu > 0) {
|
||||
lim->lim_accu -= (long long)lim->lim_max_rate * elapsed / LIMITER_TIME_RESOLUTION;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lim->lim_accu = amount;
|
||||
lim->lim_stamp = now;
|
||||
lim->lim_rate = 0;
|
||||
}
|
||||
|
||||
elapsed -= LIMITER_TIME_RESOLUTION * 2;
|
||||
if (elapsed > LIMITER_TIME_RESOLUTION) {
|
||||
lim->lim_stamp += elapsed;
|
||||
if (lim->lim_accu > 0)
|
||||
lim->lim_accu -= (long long)lim->lim_max_rate * elapsed / LIMITER_TIME_RESOLUTION;
|
||||
}
|
||||
} else {
|
||||
lim->lim_accu = amount;
|
||||
lim->lim_stamp = now;
|
||||
lim = lim->lim_father;
|
||||
}
|
||||
return res;
|
||||
return delay;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mars_limit);
|
||||
|
@ -9,11 +9,15 @@
|
||||
#define LIMITER_TIME_RESOLUTION NSEC_PER_SEC
|
||||
|
||||
struct mars_limiter {
|
||||
/* hierarchy tree */
|
||||
struct mars_limiter *lim_father;
|
||||
/* tunables */
|
||||
int lim_max_rate;
|
||||
/* readable */
|
||||
int lim_rate;
|
||||
unsigned long long lim_stamp;
|
||||
/* internal */
|
||||
int lim_accu;
|
||||
unsigned long long lim_stamp;
|
||||
};
|
||||
|
||||
extern int mars_limit(struct mars_limiter *lim, int amount);
|
||||
|
Loading…
Reference in New Issue
Block a user