Replace calls to time.After with time.NewTimer for explicit stopping

This commit is contained in:
Daniel Smith
2015-05-04 14:29:33 -07:00
parent 838b59cb4d
commit 16a6fb8ef7
6 changed files with 48 additions and 18 deletions

View File

@@ -106,17 +106,24 @@ var (
errorStopRequested = errors.New("Stop requested")
)
// resyncChan returns a channel which will receive something when a resync is required.
func (r *Reflector) resyncChan() <-chan time.Time {
// resyncChan returns a channel which will receive something when a resync is
// required, and a cleanup function.
func (r *Reflector) resyncChan() (<-chan time.Time, func() bool) {
if r.resyncPeriod == 0 {
return neverExitWatch
return neverExitWatch, func() bool { return false }
}
return time.After(r.resyncPeriod)
// The cleanup function is required: imagine the scenario where watches
// always fail so we end up listing frequently. Then, if we don't
// manually stop the timer, we could end up with many timers active
// concurrently.
t := time.NewTimer(r.resyncPeriod)
return t.C, t.Stop
}
func (r *Reflector) listAndWatch(stopCh <-chan struct{}) {
var resourceVersion string
resyncCh := r.resyncChan()
resyncCh, cleanup := r.resyncChan()
defer cleanup()
list, err := r.listerWatcher.List()
if err != nil {

View File

@@ -18,6 +18,7 @@ package cache
import (
"fmt"
"math/rand"
"strconv"
"testing"
"time"
@@ -95,7 +96,8 @@ func TestRunUntil(t *testing.T) {
func TestReflector_resyncChan(t *testing.T) {
s := NewStore(MetaNamespaceKeyFunc)
g := NewReflector(&testLW{}, &api.Pod{}, s, time.Millisecond)
a, b := g.resyncChan(), time.After(100*time.Millisecond)
a, _ := g.resyncChan()
b := time.After(100 * time.Millisecond)
select {
case <-a:
t.Logf("got timeout as expected")
@@ -104,6 +106,18 @@ func TestReflector_resyncChan(t *testing.T) {
}
}
func BenchmarkReflector_resyncChanMany(b *testing.B) {
s := NewStore(MetaNamespaceKeyFunc)
g := NewReflector(&testLW{}, &api.Pod{}, s, 25*time.Millisecond)
// The improvement to this (calling the timer's Stop() method) makes
// this benchmark about 40% faster.
for i := 0; i < b.N; i++ {
g.resyncPeriod = time.Duration(rand.Float64() * float64(time.Millisecond) * 25)
_, stop := g.resyncChan()
stop()
}
}
func TestReflector_watchHandlerError(t *testing.T) {
s := NewStore(MetaNamespaceKeyFunc)
g := NewReflector(&testLW{}, &api.Pod{}, s, 0)