Я хочу выполнить функцию на не менее чем заданного интервала в Go, измеренного от начала одного вызова до начала следующего вызова.Сама функция будет различаться по времени выполнения.
Если функция выполняется дольше этого интервала, я хочу немедленно запустить ее снова.Но если / когда он в конечном итоге возобновляет выполнение менее чем за полный интервал, я хочу, чтобы он немедленно возобновил ожидание до следующей границы интервала.
Для контекста это ограничитель скорости - вызываемая функция можетлегко вращать процессор, но это не будет приносить дополнительную ценность, поскольку он взаимодействует с людьми, которые не могут реагировать так быстро.
Пример для ясности (interval == 20ms
в примере):
runtime: 15ms
wait: 5ms
runtime: 25ms
wait: 0ms
runtime: 25ms
wait: 0ms
runtime: 15ms
wait: 5ms <-- this is the important bit
Если я использую time.Ticker
, я полагаю, что дополнительные «тики» либо будут помещены в очередь в канале Ticker.C
(если он буферизован), что заставит его выполнять несколько вызовов без задержки при возобновлении, либо тикерWriter заблокирует запись в канал и в конечном итоге возобновит работу с чрезмерно большой задержкой для первого возобновления после вызова.
Сейчас я занимаюсь какой-то математикой, которая работает, но кажется, чтобыть не идиоматичным:
minDurationBetweenRuns := time.Millisecond * 100
for {
lastRunTime := time.Now()
DO_STUFF_HERE()
durationSinceLastRun := time.Now().Sub(lastRunTime)
if durationSinceLastRun < minDurationBetweenRuns {
sleepTime := minDurationBetweenRuns - durationSinceLastRun
if sleepTime > minDurationBetweenRuns {
sleepTime = minDurationBetweenRuns
}
time.Sleep(sleepTime)
}
}