ratecounter
ratecounter copied to clipboard
Inaccurate when under load
The current implementation of the rate counter assumes that time.NewTicker will tick (write to the channel) at every (interval / resolution). However, when the application and/or CPU has a heavy load, this ticker is designed such that it "adjusts the intervals or drops ticks to make up for slow receivers". The end result is a very incorrect rate count, in these conditions.
Hmmm.. Any suggestions on ways to solve this?
Not sure how precise this is, but for my purposes I created a baseline rate counter like this:
const baselineTickerResolution = 100
ticker := time.NewTicker(time.Second / baselineTickerResolution)
for range ticker.C {
baselineRateCounter.Incr(1)
}
then scaled the values by the baseline rate counter:
rate := rateCounter.Rate()
baselineRate := baselineRateCounter.Rate()
driftRatio := float64(baselineRate) / float64(baselineTickerResolution)
finalRate := int64(float64(rate) * driftRatio)
The idea was that if one ticker gets bogged down by CPU load, the other will too, to a similar degree.
This makes some assumptions about thread scheduler fairness under load. Without the baseline the reported value will always be between 0-1x of actual. With the baseline adjustment, the reported value will be between 0-100x the actual value.
Also, the baseline adjustment is somewhat “making up data", which makes me a bit uncomfortable. For me, the failure mode of “didn’t count everything” is preferable to the failure mode of “counted things which didn’t happen”.
Maybe a solution would be to not be dependent on a ticker getting called at a consistent rate. i.e. take into account how much time has passed since the last update, and divide the total count since the last update by that amount? I think that would always result in a 0-1x value, due to the ticker dropping ticks.
Hmm, that might work, and would actually be an improvement on assuming Ticker is called every second. Any interest in sending a PR to do that?
Not at this time; I don't really have any urgent need for it right now.