Git Product home page Git Product logo

equalizer's Introduction

equalizer

The equalizer package provides a set of simple and easy-to-use rate limiters for Go. These rate limiters can be used to limit the rate of requests to any resource, such as a database, API, or file.

The package includes the following rate limiters:

Equalizer

Equalizer is a rate limiter that adjusts the rate of requests based on the outcomes of previous requests. If previous attempts have failed, Equalizer will slow down the rate of requests to avoid overloading the system. Conversely, if previous attempts have been successful, Equalizer will accelerate the rate of requests to make the most of the available capacity.

Usage Example

// a random offset manager 
offset := equalizer.NewRandomOffset(96)
// an Equalizer with a bitmap size of 96, 16 reserved positive bits, and the random offset manager
eq := equalizer.NewEqualizer(96, 16, offset)
// non-blocking quota request
haveQuota := eq.TryAcquire()
// update on the successful request
eq.Success(1)

Benchmarks

BenchmarkEqualizer_ShortTryAcquireStep-16       31538967                38.33 ns/op            0 B/op          0 allocs/op
BenchmarkEqualizer_ShortTryAcquireRandom-16     37563639                31.66 ns/op            0 B/op          0 allocs/op
BenchmarkEqualizer_ShortNotify-16               29519719                40.43 ns/op            0 B/op          0 allocs/op
BenchmarkEqualizer_LongTryAcquireStep-16        32084402                38.36 ns/op            0 B/op          0 allocs/op
BenchmarkEqualizer_LongTryAcquireRandom-16      39996501                30.37 ns/op            0 B/op          0 allocs/op
BenchmarkEqualizer_LongNotify-16                29648655                40.46 ns/op            0 B/op          0 allocs/op

Slider

Slider tracks the number of requests that have been processed in a recent time window. If the number of requests exceeds the limit, the rate limiter will block new requests until the window has moved forward. Implements the equalizer.Limiter interface.

Usage Example

// a Slider with a one-second window size, a 100-millisecond sliding interval,
// and a capacity of 32
slider := equalizer.NewSlider(time.Second, 100*time.Millisecond, 32)
// non-blocking quota request
haveQuota := slider.TryAcquire()
// blocking call
slider.Acquire(context.Background())

Benchmarks

BenchmarkSlider_TryAcquire-16                   293645348                4.033 ns/op           0 B/op          0 allocs/op
BenchmarkRateLimiter_Allow-16                     9362382              127.4 ns/op             0 B/op          0 allocs/op

* Compared to rate.Limiter from the golang.org/x/time package.

Token Bucket

TokenBucket maintains a fixed number of tokens. Each token represents a request that can be processed. When a request is made, the rate limiter checks to see if there are any available tokens. If there are, the request is processed and one token is removed from the bucket. If there are no available tokens, the request is blocked until a token becomes available. Implements the equalizer.Limiter interface.

Usage Example

// a TokenBucket with the capacity of 32 and a 100-millisecond refill interval
tokenBucket := equalizer.NewTokenBucket(32, 100*time.Millisecond)
// non-blocking quota request
haveQuota := tokenBucket.TryAcquire()
// blocking call
tokenBucket.Acquire(context.Background())

Benchmarks

BenchmarkTokenBucket_TryAcquire-16              304653043                3.909 ns/op           0 B/op          0 allocs/op
BenchmarkRateLimiter_Allow-16                     9362382              127.4 ns/op             0 B/op          0 allocs/op

* Compared to rate.Limiter from the golang.org/x/time package.

License

Licensed under the MIT License.

equalizer's People

Contributors

reugn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

equalizer's Issues

tokenBucket: incorrect count of issued when refill

// refill refills the token bucket.
func (tb *tokenBucket) refill() {
issued := atomic.LoadInt32(&tb.issued)
atomic.StoreInt32(&tb.issued, 0)
tb.fillTokenBucket(int(issued))
}
// Ask requires a permit.
// It is a non blocking call, returns true or false.
func (tb *TokenBucket) Ask() bool {
select {
case <-tb.t.permits:
atomic.AddInt32(&tb.t.issued, 1)
return true

A token can be issued between line 68 and 69 and then it will lead to a incorrect issued count and decrease the bucket real capacity.

Example:
refill() and Ask() executes concurrently then:
line 68 executes
line 77 and 78 executes
line 69 and 70 executes

Solution:
issued := atomic.SwapInt32(&tb.issued, 0)

Maybe consider context.Context for blocking Take()

Thanks for providing this simple library!
One thing I noted is that Take() cannot be interrupted if it takes very long (some api limits are very strict), so for example it will considerably delay aborting an action. Could you maybe consider to provide a Take operation which can be interrupted through a context object? That would be a great improvement!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.