Documentation
¶
Index ¶
- type Limiter
- func (l *Limiter) Borrow(now time.Time, v float64) time.Duration
- func (l *Limiter) Capacity() float64
- func (l *Limiter) Have(now time.Time, v float64) bool
- func (l *Limiter) Rate() float64
- func (l *Limiter) Return(now time.Time, v float64)
- func (l *Limiter) Set(now time.Time, v float64) float64
- func (l *Limiter) Take(now time.Time, v float64) bool
- func (l *Limiter) Update(now time.Time, rate, cap float64)
- func (l *Limiter) Value(now time.Time) float64
- type Option
- type OptionFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Limiter ¶
type Limiter struct {
// contains filtered or unexported fields
}
Limiter uses classic token bucket algorithm. Bucket is full when created.
func NewLimiter ¶
NewLimiter creates new token bucket limiter. Bucket is full when created. Use it to limit to at most rate per second tokens with at most cap burst.
Each operaion takes current time and updates the state as it was filled up continuously. If time goes backwards it's ignored as it was already accounted. Thus you can't take unused tokens from the past if bucket is full now.
Limiter is not safe to use in parallel.
func (*Limiter) Borrow ¶
Borrow takes v tokens even if there is not enough of them and returns the time needed to wait before using them. If there was enough tokens the returned time is 0. Borrow can take even more tokens then burst capacity. Callers must check for Capacity on their own.
Example (Full) ¶
package main
import (
"fmt"
"time"
"nikand.dev/go/rate"
)
type WriterFunc func([]byte) (int, error)
func (f WriterFunc) Write(p []byte) (int, error) {
return f(p)
}
func main() {
// Mind we want to limit output speed for tcp connection.
// Out test fake time
base := time.Now()
now := base
// downstream writer
w := WriterFunc(func(p []byte) (int, error) {
fmt.Printf("%5d bytes written at %v\n", len(p), now.Sub(base))
return len(p), nil
})
var r *rate.Limiter // will init later
// the actual usage example of rate.Limiter
limitedWrite := func(p []byte) (n int, err error) {
var m int
lim := len(p)
if c := r.Capacity(); float64(lim) > c {
lim = int(c)
}
for err == nil && n < len(p) {
if lim > len(p)-n {
lim = len(p) - n
}
delay := r.Borrow(now, float64(lim))
if delay > 0 {
now = now.Add(delay) // time.Sleep(delay)
}
m, err = w.Write(p[n : n+lim])
n += m
}
return
}
fmt.Printf("Max burst of 515 bytes with rate of 1KiB per second\n")
tRate := float64(1*1024) / time.Second.Seconds() // 1KiB per second
burst := float64(512) // 128 bytes at once at most
r = rate.NewLimiter(now, tRate, burst)
_, _ = limitedWrite(make([]byte, 5*1024))
}
Output: Max burst of 515 bytes with rate of 1KiB per second 512 bytes written at 0s 512 bytes written at 500ms 512 bytes written at 1s 512 bytes written at 1.5s 512 bytes written at 2s 512 bytes written at 2.5s 512 bytes written at 3s 512 bytes written at 3.5s 512 bytes written at 4s 512 bytes written at 4.5s
func (*Limiter) Return ¶
Return returns borrowed time back. If current value + returned v > Capacity it's truncated.
func (*Limiter) Set ¶
Set sets current limiter state. It can be used to drain or fill the Limiter. Returns previous value.
func (*Limiter) Take ¶
Take takes v tokens if there is enough of them. Take returns true if taken and false otherwise.
Example (Full) ¶
package main
import (
"errors"
"fmt"
"io"
"time"
"nikand.dev/go/rate"
)
func main() {
// Mind we want to limit packets bandwidth.
// Out test fake time
base := time.Now()
now := base
// downstream writer
w := io.Discard
var ErrSpeedLimited = errors.New("speed limited")
var r *rate.Limiter // will init later
// the actual usage example of rate.Limiter
limitedWrite := func(p []byte) (n int, err error) {
if !r.Take(now, float64(len(p))) {
return 0, ErrSpeedLimited
}
return w.Write(p)
}
fmt.Printf("Max burst of 2KiB with rate of 1KiB per second\n")
tRate := float64(1*1024) / time.Second.Seconds() // 1KiB per second
burst := float64(2 * 1024) // 2KiB at once at most
r = rate.NewLimiter(now, tRate, burst)
for i := 0; i < 4; i++ {
n, err := limitedWrite(make([]byte, 1024))
fmt.Printf("time %5v: %d %v\n", now.Sub(base), n, err)
now = now.Add(time.Second / 2)
}
}
Output: Max burst of 2KiB with rate of 1KiB per second time 0s: 1024 <nil> time 500ms: 1024 <nil> time 1s: 1024 <nil> time 1.5s: 0 speed limited