mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-07-11 07:36:38 -07:00
Add a concept of debt to RateLimiter, save a bit of RAM.
This commit is contained in:
parent
3af55f4423
commit
6a24ac4f00
4 changed files with 58 additions and 34 deletions
|
@ -46,6 +46,31 @@ namespace ZeroTier {
|
|||
class RateLimiter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Limits to apply to a rate limiter
|
||||
*
|
||||
* Since many rate limiters may share the same fixed limit values,
|
||||
* save memory by breaking this out into a struct parameter that
|
||||
* can be passed into RateLimiter's methods.
|
||||
*/
|
||||
struct Limit
|
||||
{
|
||||
/**
|
||||
* Speed in bytes per second, or rate of balance accrual
|
||||
*/
|
||||
double bytesPerSecond;
|
||||
|
||||
/**
|
||||
* Maximum balance that can ever be accrued (should be > 0.0)
|
||||
*/
|
||||
double maxBalance;
|
||||
|
||||
/**
|
||||
* Minimum balance, or maximum allowable "debt" (should be <= 0.0)
|
||||
*/
|
||||
double minBalance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an uninitialized rate limiter
|
||||
*
|
||||
|
@ -54,70 +79,58 @@ public:
|
|||
RateLimiter() throw() {}
|
||||
|
||||
/**
|
||||
* @param bytesPerSecond Bytes per second to permit (average)
|
||||
* @param preload Initial balance to place in account
|
||||
* @param max Maximum balance to permit to ever accrue (max burst)
|
||||
*/
|
||||
RateLimiter(double bytesPerSecond,double preload,double max)
|
||||
RateLimiter(double preload)
|
||||
throw()
|
||||
{
|
||||
init(bytesPerSecond,preload,max);
|
||||
init(preload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize or re-initialize rate limiter
|
||||
*
|
||||
* @param bytesPerSecond Bytes per second to permit (average)
|
||||
* @param preload Initial balance to place in account
|
||||
* @param max Maximum balance to permit to ever accrue (max burst)
|
||||
*/
|
||||
inline void init(double bytesPerSecond,double preload,double max)
|
||||
inline void init(double preload)
|
||||
throw()
|
||||
{
|
||||
_bytesPerSecond = bytesPerSecond;
|
||||
_lastTime = Utils::nowf();
|
||||
_balance = preload;
|
||||
_max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update balance based on current clock
|
||||
*
|
||||
* This can be called at any time to check the current balance without
|
||||
* affecting the behavior of gate().
|
||||
* Update balance based on current clock and supplied Limits bytesPerSecond and maxBalance
|
||||
*
|
||||
* @param lim Current limits in effect
|
||||
* @return New balance
|
||||
*/
|
||||
inline double updateBalance()
|
||||
inline double updateBalance(const Limit &lim)
|
||||
throw()
|
||||
{
|
||||
double now = Utils::nowf();
|
||||
double b = _balance = fmin(_max,_balance + (_bytesPerSecond * (now - _lastTime)));
|
||||
_lastTime = now;
|
||||
return b;
|
||||
double lt = _lastTime;
|
||||
double now = _lastTime = Utils::nowf();
|
||||
return (_balance = fmin(lim.maxBalance,_balance + (lim.bytesPerSecond * (now - lt))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test balance and update / deduct if there is enough to transfer 'bytes'
|
||||
* Update balance and test if a block of 'bytes' should be permitted to be transferred
|
||||
*
|
||||
* @param lim Current limits in effect
|
||||
* @param bytes Number of bytes that we wish to transfer
|
||||
* @return True if balance was sufficient (balance is updated), false if not (balance unchanged)
|
||||
* @return True if balance was sufficient
|
||||
*/
|
||||
inline bool gate(double bytes)
|
||||
inline bool gate(const Limit &lim,double bytes)
|
||||
throw()
|
||||
{
|
||||
if (updateBalance() >= bytes) {
|
||||
_balance -= bytes;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool allow = (updateBalance(lim) >= bytes);
|
||||
_balance = fmax(lim.minBalance,_balance - bytes);
|
||||
return allow;
|
||||
}
|
||||
|
||||
private:
|
||||
double _bytesPerSecond;
|
||||
double _lastTime;
|
||||
double _balance;
|
||||
double _max;
|
||||
};
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue