ratecounter icon indicating copy to clipboard operation
ratecounter copied to clipboard

Inaccurate when under load

Open EmpireJones opened this issue 6 years ago • 6 comments

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.

EmpireJones avatar Nov 09 '17 20:11 EmpireJones

Hmmm.. Any suggestions on ways to solve this?

paulbellamy avatar Dec 16 '17 10:12 paulbellamy

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.

EmpireJones avatar Dec 22 '17 06:12 EmpireJones

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”.

paulbellamy avatar Dec 22 '17 16:12 paulbellamy

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.

EmpireJones avatar Dec 23 '17 04:12 EmpireJones

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?

paulbellamy avatar Dec 27 '17 11:12 paulbellamy

Not at this time; I don't really have any urgent need for it right now.

EmpireJones avatar Dec 29 '17 05:12 EmpireJones