Algorithm-TokenBucket
view release on metacpan or search on metacpan
lib/Algorithm/TokenBucket.pm view on Meta::CPAN
}
# 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.
Each bucket has a constant memory footprint because the algorithm is based
on the C<information rate>. Other rate limiters may keep track of
I<ALL> incoming items in memory. It allows them to be more accurate.
FYI, the C<conform>, C<count>, C<information rate>, and C<burst size> terms
are taken from the L<metering primitives|http://linux-ip.net/gl/tcng/node62.html>
page of the L<Linux Traffic Control - Next Generation|http://linux-ip.net/gl/tcng/>
system documentation.
=head1 INTERFACE
=cut
use fields qw/info_rate burst_size _tokens _last_check_time/;
=head2 METHODS
=over 4
=item new($$;$$)
The constructor requires at least the C<rate of information> in items per
second and the C<burst size> in items as its input parameters. It can also
take the current token counter and last check time but this usage is mostly
intended for restoring a saved bucket. See L</state()>.
=cut
sub new {
my $class = shift;
fields::new($class)->_init(@_);
}
sub _init {
my Algorithm::TokenBucket $self = shift;
@$self{qw/info_rate burst_size _tokens _last_check_time/} = @_;
$self->{_last_check_time} ||= time;
$self->{_tokens} ||= 0;
return $self;
}
=item state()
Returns the state of the bucket as a list. Use it for storing purposes.
Buckets also natively support freezing and thawing with L<Storable> by
providing C<STORABLE_*> callbacks.
=cut
sub state {
my Algorithm::TokenBucket $self = shift;
return @$self{qw/info_rate burst_size _tokens _last_check_time/};
}
use constant PACK_FORMAT => "d4"; # "F4" is not 5.6 compatible
sub STORABLE_freeze {
my ($self, $cloning) = @_;
return pack(PACK_FORMAT(), $self->state);
}
sub STORABLE_thaw {
my ($self, $cloning, $state) = @_;
return $self->_init(unpack(PACK_FORMAT(), $state));
}
sub _token_flow {
my Algorithm::TokenBucket $self = shift;
my $time = time;
$self->{_tokens} +=
($time - $self->{_last_check_time}) * $self->{info_rate};
if ($self->{_tokens} > $self->{burst_size}) {
$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;
return $self->{_tokens} >= $size;
}
=item count($)
This method removes I<N> (or all if there are fewer than I<N> available)
tokens from the bucket. It does not return a meaningful value.
=cut
( run in 0.602 second using v1.01-cache-2.11-cpan-9288abcf80b )