Algorithm-TokenBucket
view release on metacpan or search on metacpan
Algorithm::TokenBucket - Token bucket rate limiting algorithm
# SYNOPSIS
use Algorithm::TokenBucket;
# configure a bucket to limit a stream up to 100 items per hour
# with bursts of 5 items max
my $bucket = Algorithm::TokenBucket->new(100 / 3600, 5);
# wait until we are allowed to process 3 items
until ($bucket->conform(3)) {
sleep 0.1;
# do things
}
# process 3 items because we now can
process(3);
# leak (flush) bucket
$bucket->count(3); # same as $bucket->count(1) for 1..3;
if ($bucket->conform(10)) {
die;
# because a bucket with the burst size of 5
# will never conform to 10
}
my $time = Time::HiRes::time;
while (Time::HiRes::time - $time < 7200) { # two hours
# be bursty
if ($bucket->conform(5)) {
process(5);
$bucket->count(5);
}
}
# we're likely to have processed 200 items (and hogged CPU)
Storable::store $bucket, 'bucket.stored';
my $bucket1 =
Algorithm::TokenBucket->new(@{Storable::retrieve('bucket.stored')});
# DESCRIPTION
The Token Bucket algorithm is a flexible way of imposing a rate limit
against a stream of items. It is also very easy to combine several
rate-limiters in an `AND` or `OR` fashion.
- state()
Returns the state of the bucket as a list. Use it for storing purposes.
Buckets also natively support freezing and thawing with [Storable](https://metacpan.org/pod/Storable) by
providing `STORABLE_*` callbacks.
- conform($)
This method returns true if the bucket contains at least _N_ tokens and
false otherwise. In the case that it is true, it is allowed to transmit or
process _N_ items (not exactly right because _N_ can be fractional) from
the stream. A bucket never conforms to an _N_ greater than `burst size`.
- count($)
This method removes _N_ (or all if there are fewer than _N_ available)
tokens from the bucket. It does not return a meaningful value.
- until($)
This method returns the number of seconds until _N_ tokens can be removed
Now, let's fix the CPU-hogging example from ["SYNOPSIS"](#synopsis) using
the ["until($)"](#until) method.
my $bucket = Algorithm::TokenBucket->new(100 / 3600, 5);
my $time = Time::HiRes::time;
while (Time::HiRes::time - $time < 7200) { # two hours
# be bursty
Time::HiRes::sleep $bucket->until(5);
if ($bucket->conform(5)) { # should always be true
process(5);
$bucket->count(5);
}
}
# we're likely to have processed 200 items (without hogging the CPU)
# BUGS
Documentation lacks the actual algorithm description. See links or read
the source (there are about 20 lines of sparse Perl in several subs).
`until($N)` does not return infinity if `$N` is greater than `burst
size`. Sleeping for infinity seconds is both useless and hard to debug.
# ACKNOWLEDGMENTS
lib/Algorithm/TokenBucket.pm view on Meta::CPAN
Algorithm::TokenBucket - Token bucket rate limiting algorithm
=head1 SYNOPSIS
use Algorithm::TokenBucket;
# configure a bucket to limit a stream up to 100 items per hour
# with bursts of 5 items max
my $bucket = Algorithm::TokenBucket->new(100 / 3600, 5);
# wait until we are allowed to process 3 items
until ($bucket->conform(3)) {
sleep 0.1;
# do things
}
# process 3 items because we now can
process(3);
# leak (flush) bucket
$bucket->count(3); # same as $bucket->count(1) for 1..3;
if ($bucket->conform(10)) {
die;
# because a bucket with the burst size of 5
# will never conform to 10
}
my $time = Time::HiRes::time;
while (Time::HiRes::time - $time < 7200) { # two hours
# be bursty
if ($bucket->conform(5)) {
process(5);
$bucket->count(5);
}
}
# we're likely to have processed 200 items (and hogged CPU)
Storable::store $bucket, 'bucket.stored';
my $bucket1 =
Algorithm::TokenBucket->new(@{Storable::retrieve('bucket.stored')});
=head1 DESCRIPTION
The Token Bucket algorithm is a flexible way of imposing a rate limit
against a stream of items. It is also very easy to combine several
rate-limiters in an C<AND> or C<OR> fashion.
lib/Algorithm/TokenBucket.pm view on Meta::CPAN
$self->{_tokens} = $self->{burst_size};
}
$self->{_last_check_time} = $time;
}
=item conform($)
This method returns true if the bucket contains at least I<N> tokens and
false otherwise. In the case that it is true, it is allowed to transmit or
process I<N> items (not exactly right because I<N> can be fractional) from
the stream. A bucket never conforms to an I<N> greater than C<burst size>.
=cut
sub conform {
my Algorithm::TokenBucket $self = shift;
my $size = shift;
$self->_token_flow;
lib/Algorithm/TokenBucket.pm view on Meta::CPAN
Now, let's fix the CPU-hogging example from L</SYNOPSIS> using
the L</until($)> method.
my $bucket = Algorithm::TokenBucket->new(100 / 3600, 5);
my $time = Time::HiRes::time;
while (Time::HiRes::time - $time < 7200) { # two hours
# be bursty
Time::HiRes::sleep $bucket->until(5);
if ($bucket->conform(5)) { # should always be true
process(5);
$bucket->count(5);
}
}
# we're likely to have processed 200 items (without hogging the CPU)
=head1 BUGS
Documentation lacks the actual algorithm description. See links or read
the source (there are about 20 lines of sparse Perl in several subs).
C<until($N)> does not return infinity if C<$N> is greater than C<burst
size>. Sleeping for infinity seconds is both useless and hard to debug.
=head1 ACKNOWLEDGMENTS
( run in 0.479 second using v1.01-cache-2.11-cpan-8d75d55dd25 )