Reputation: 2367
Not able to find out where in the below for loop we are spending more than ten microseconds so that we are missing vast number of ticks?
package main
import (
"context"
"fmt"
"time"
)
func main() {
RunTicker(time.Millisecond, 10 * time.Second) // Scenario 1
RunTicker(10 * time.Microsecond, 10 * time.Second) // Scenario 2
}
func RunTicker(tickerInterval, tickerDuration time.Duration) {
var counter int
ctx, can := context.WithTimeout(context.Background(), tickerDuration)
defer can()
ticker := time.NewTicker(tickerInterval)
exitfor:
for {
select {
case <-ticker.C:
counter++
case <- ctx.Done():
ticker.Stop()
break exitfor
}
}
fmt.Printf("Tick interval %v and running for %v.Expected counter: %d but got %d\n", tickerInterval, tickerDuration, tickerDuration/tickerInterval, counter)
}
Output:
Tick interval 1ms and running for 10s.Expected counter: 10000 but got 9965
Tick interval 10µs and running for 10s.Expected counter: 1000000 but got 976590
Upvotes: 2
Views: 2538
Reputation: 8425
In general, when an API says that an event will take X seconds, it's actually guaranteeing that the elapsed time will be at least X seconds, and not less. Especially for small time increments, this is an important distinction.
Also, consider this point from the NewTicker documentation:
The period of the ticks is specified by the duration argument. The ticker will adjust the time interval or drop ticks to make up for slow receivers.
With these two points in mind, the only guarantee you really have is that the number of real ticks will be <= to the expected number you calculate, and no more. In other words, actual ticks == expected ticks only in the ideal case, and every other case will be less than that.
In these kinds of small time increments (~< 1ms), there could be other events besides "user code" that exceed the tick time including:
These other factors can coincide, making it even more likely that a tick will be skipped or delayed.
Think of it like you have a bucket full of water, and you need to pour it into another bucket, and then another bucket, and another one and so on for 1000s of buckets. The only thing you can do is lose water, and you can't gain any more once it's spilled. With this scenario, you would never expect to retain 100% of the water to the very end.
This is similar to the case you mention because the errors only go in one direction. Delays can only be at least the specified time, and ticks can only be lost (extras are never gained). Any time any of these events happen, it's like a drop of water is lost.
Upvotes: 9