@@ -186,6 +186,9 @@ type Cacher struct {
186
186
stopped bool
187
187
stopCh chan struct {}
188
188
stopWg sync.WaitGroup
189
+
190
+ // Used to avoid unnecessary allocations in underlying watchers.
191
+ timer * time.Timer
189
192
}
190
193
191
194
// NewCacherFromConfig creates a new Cacher responsible for servicing WATCH and LIST requests from
@@ -227,6 +230,7 @@ func NewCacherFromConfig(config Config) *Cacher {
227
230
// and there are no guarantees on the order that they will stop.
228
231
// So we will be simply closing the channel, and synchronizing on the WaitGroup.
229
232
stopCh : stopCh ,
233
+ timer : time .NewTimer (time .Duration (0 )),
230
234
}
231
235
watchCache .SetOnEvent (cacher .processEvent )
232
236
go cacher .dispatchEvents ()
@@ -242,6 +246,14 @@ func NewCacherFromConfig(config Config) *Cacher {
242
246
}, time .Second , stopCh ,
243
247
)
244
248
}()
249
+
250
+ // Ensure that timer is stopped.
251
+ if ! cacher .timer .Stop () {
252
+ // Consume triggered (but not yet received) timer event
253
+ // so that future reuse does not get a spurious timeout.
254
+ <- cacher .timer .C
255
+ }
256
+
245
257
return cacher
246
258
}
247
259
@@ -621,13 +633,13 @@ func (c *Cacher) dispatchEvent(event *watchCacheEvent) {
621
633
defer c .Unlock ()
622
634
// Iterate over "allWatchers" no matter what the trigger function is.
623
635
for _ , watcher := range c .watchers .allWatchers {
624
- watcher .add (event , c .dispatchTimeoutBudget )
636
+ watcher .add (event , c .timer , c . dispatchTimeoutBudget )
625
637
}
626
638
if supported {
627
639
// Iterate over watchers interested in the given values of the trigger.
628
640
for _ , triggerValue := range triggerValues {
629
641
for _ , watcher := range c .watchers .valueWatchers [triggerValue ] {
630
- watcher .add (event , c .dispatchTimeoutBudget )
642
+ watcher .add (event , c .timer , c . dispatchTimeoutBudget )
631
643
}
632
644
}
633
645
} else {
@@ -640,7 +652,7 @@ func (c *Cacher) dispatchEvent(event *watchCacheEvent) {
640
652
// Iterate over watchers interested in exact values for all values.
641
653
for _ , watchers := range c .watchers .valueWatchers {
642
654
for _ , watcher := range watchers {
643
- watcher .add (event , c .dispatchTimeoutBudget )
655
+ watcher .add (event , c .timer , c . dispatchTimeoutBudget )
644
656
}
645
657
}
646
658
}
@@ -826,9 +838,7 @@ func (c *cacheWatcher) stop() {
826
838
}
827
839
}
828
840
829
- var timerPool sync.Pool
830
-
831
- func (c * cacheWatcher ) add (event * watchCacheEvent , budget * timeBudget ) {
841
+ func (c * cacheWatcher ) add (event * watchCacheEvent , timer * time.Timer , budget * timeBudget ) {
832
842
// Try to send the event immediately, without blocking.
833
843
select {
834
844
case c .input <- event :
@@ -842,23 +852,16 @@ func (c *cacheWatcher) add(event *watchCacheEvent, budget *timeBudget) {
842
852
startTime := time .Now ()
843
853
timeout := budget .takeAvailable ()
844
854
845
- t , ok := timerPool .Get ().(* time.Timer )
846
- if ok {
847
- t .Reset (timeout )
848
- } else {
849
- t = time .NewTimer (timeout )
850
- }
851
- defer timerPool .Put (t )
855
+ timer .Reset (timeout )
852
856
853
857
select {
854
858
case c .input <- event :
855
- stopped := t .Stop ()
856
- if ! stopped {
859
+ if ! timer .Stop () {
857
860
// Consume triggered (but not yet received) timer event
858
861
// so that future reuse does not get a spurious timeout.
859
- <- t .C
862
+ <- timer .C
860
863
}
861
- case <- t .C :
864
+ case <- timer .C :
862
865
// This means that we couldn't send event to that watcher.
863
866
// Since we don't want to block on it infinitely,
864
867
// we simply terminate it.
0 commit comments