Advance should be called by an external ticker every sketchDuration to advance the ring. It advances at least 1 step per call.
()
| 105 | // Advance should be called by an external ticker every sketchDuration to advance the ring. |
| 106 | // It advances at least 1 step per call. |
| 107 | func (c *Cardinality) Advance() { |
| 108 | c.mu.Lock() |
| 109 | delta := time.Since(c.lastAdvance) |
| 110 | steps := 0 |
| 111 | if delta < c.sketchDuration { |
| 112 | steps = 1 |
| 113 | } else { |
| 114 | steps = int(delta / c.sketchDuration) |
| 115 | } |
| 116 | // Cap steps so we don't loop excessively after very long pauses. |
| 117 | if steps > c.sketchesLength { |
| 118 | steps = c.sketchesLength |
| 119 | } |
| 120 | |
| 121 | for i := 0; i < steps; i++ { |
| 122 | // advance ring |
| 123 | c.current++ |
| 124 | if c.current >= c.sketchesLength { |
| 125 | c.current = 0 |
| 126 | } |
| 127 | // reset new current sketch |
| 128 | c.sketches[c.current], _ = hll.NewSketch(c.precision, true) |
| 129 | c.lastAdvance = c.lastAdvance.Add(c.sketchDuration) |
| 130 | } |
| 131 | |
| 132 | // Recompute cached merge of all non-current sketches |
| 133 | cachedMerge, _ := hll.NewSketch(c.precision, true) |
| 134 | for i := 0; i < c.sketchesLength; i++ { |
| 135 | if i == c.current { |
| 136 | continue |
| 137 | } |
| 138 | _ = cachedMerge.Merge(c.sketches[i]) |
| 139 | } |
| 140 | c.cachedMerge = cachedMerge |
| 141 | c.mu.Unlock() |
| 142 | } |