-
Notifications
You must be signed in to change notification settings - Fork 353
/
Copy pathbinarysampler.go
62 lines (51 loc) · 1.11 KB
/
binarysampler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package circuit
// binarysampler contains a series of events as 0 or 1 values, e.g. errors or successes,
// within a limited, sliding window.
// count contains the actual number of events with the value of 1 within the window.
// it compresses the event storage by 64.
type binarySampler struct {
size int
filled int
frames []uint64
pad uint64
count int
}
func newBinarySampler(size int) *binarySampler {
if size <= 0 {
size = 1
}
return &binarySampler{
size: size,
pad: 64 - uint64(size)%64,
}
}
func highestSet(frame, pad uint64) bool {
return frame&(1<<(63-pad)) != 0
}
func shift(frames []uint64) {
highestFrame := len(frames) - 1
for i := highestFrame; i >= 0; i-- {
h := highestSet(frames[i], 0)
frames[i] = frames[i] << 1
if h && i < highestFrame {
frames[i+1] |= 1
}
}
}
func (s *binarySampler) tick(set bool) {
filled := s.filled == s.size
if filled && highestSet(s.frames[len(s.frames)-1], s.pad) {
s.count--
}
if !filled {
if len(s.frames) <= s.filled/64 {
s.frames = append(s.frames, 0)
}
s.filled++
}
shift(s.frames)
if set {
s.count++
s.frames[0] |= 1
}
}