gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/grpc/balancer/rls/internal/adaptive/lookback.go (about) 1 /* 2 * 3 * Copyright 2020 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package adaptive 20 21 import "time" 22 23 // lookback implements a moving sum over an int64 timeline. 24 type lookback struct { 25 bins int64 // Number of bins to use for lookback. 26 width time.Duration // Width of each bin. 27 28 head int64 // Absolute bin index (time * bins / duration) of the current head bin. 29 total int64 // Sum over all the values in buf, within the lookback window behind head. 30 buf []int64 // Ring buffer for keeping track of the sum elements. 31 } 32 33 // newLookback creates a new lookback for the given duration with a set number 34 // of bins. 35 func newLookback(bins int64, duration time.Duration) *lookback { 36 return &lookback{ 37 bins: bins, 38 width: duration / time.Duration(bins), 39 buf: make([]int64, bins), 40 } 41 } 42 43 // add is used to increment the lookback sum. 44 func (l *lookback) add(t time.Time, v int64) { 45 pos := l.advance(t) 46 47 if (l.head - pos) >= l.bins { 48 // Do not increment counters if pos is more than bins behind head. 49 return 50 } 51 l.buf[pos%l.bins] += v 52 l.total += v 53 } 54 55 // sum returns the sum of the lookback buffer at the given time or head, 56 // whichever is greater. 57 func (l *lookback) sum(t time.Time) int64 { 58 l.advance(t) 59 return l.total 60 } 61 62 // advance prepares the lookback buffer for calls to add() or sum() at time t. 63 // If head is greater than t then the lookback buffer will be untouched. The 64 // absolute bin index corresponding to t is returned. It will always be less 65 // than or equal to head. 66 func (l *lookback) advance(t time.Time) int64 { 67 ch := l.head // Current head bin index. 68 nh := t.UnixNano() / l.width.Nanoseconds() // New head bin index. 69 70 if nh <= ch { 71 // Either head unchanged or clock jitter (time has moved backwards). Do 72 // not advance. 73 return nh 74 } 75 76 jmax := min(l.bins, nh-ch) 77 for j := int64(0); j < jmax; j++ { 78 i := (ch + j + 1) % l.bins 79 l.total -= l.buf[i] 80 l.buf[i] = 0 81 } 82 l.head = nh 83 return nh 84 } 85 86 func min(x int64, y int64) int64 { 87 if x < y { 88 return x 89 } 90 return y 91 }