This is a creation in Article, where the information may have evolved or changed.
Speed limiter
Before seeing this two speed-limiting methods of golang concurrent programming, I think the way sleep waits is not particularly good, and it takes longer to wake up threads. and 1s within the request can only be evenly arrived, such as an instant to N, then only one can immediately return, the rest can only wait.
Amended
According to the instructions, whether it is sleep or Chan block, what happens is G and P separation, waiting for the next rotation, then proceed, so the likelihood can be almost the same. (This statement may not be accurate, not in depth)
The role of speed limiter is still more important, especially the use of more applications, if unrestricted, may be oom.
Simple idea: The default time interval is set to 1 seconds, simplifying the problem. If the limit () bool interface is called, if the number of runs in a second reaches a certain value, then it is blocked until the next 1 seconds are re-counted.
Code
Package Libimport ("Sync/atomic" "Time") type ratelimiter struct {limit UInt64 count UInt64 Ticker *time . Ticker Lockch Chan struct{}}func newratelimiter (limit UInt64) *ratelimiter {Ticker: = time. Newticker (time. Second) R: = &ratelimiter{limit:limit, count:0, Ticker:ticker, Lockch:make (chan struct{}),} go func () {for range ticker. C {if r.count > r.limit {select {case <-r.lockch:default : R.resetcount ()}} if R.count > 0 { R.resetcount ()}}} () return R}func (R *ratelimiter) Limit () bool {R.addcou NT (1) if R.getcount () > R.limit {var s struct{} r.lockch <-s} return True}func (R *ratelim ITER) Addcount (interval UInt64) {atomic. AddUint64 (&r.count, Interval)}func (R *ratelimiter) GetCount () UInt64 {return atomic. LoadUint64 (&r.count)}func (R *ratelimiter) Resetcount () {Atomic. StoreUint64 (&r.count, 1)}
Test
package libimport ( "log" "testing" "time")func TestLimit(t *testing.T) { limiter := NewRateLimiter(3) start := time.Now() for i := 0; i < 30; i++ { if limiter.Limit() { log.Printf("i is %d \n", i) } } end := time.Now() d := end.Sub(start) log.Println("spends seconds: ", d.Seconds())}
Comparison
Compared to the first sleep implementation, the limiter is set to 3 times per second, Cycle 30 times, respectively:
2016/08/31 14:38:26 my limiter spends seconds: 9.00220346s2016/08/31 14:38:35 sleep limiter spends seconds: 9.762009934s
Here sleep limiter sleep more than two times, about 0.67s, minus this value equals 9.092009934.