diff --git a/pkg/registry/pod/strategy.go b/pkg/registry/pod/strategy.go index d739f92a837..864e5c09e33 100644 --- a/pkg/registry/pod/strategy.go +++ b/pkg/registry/pod/strategy.go @@ -163,7 +163,19 @@ func MatchPod(label labels.Selector, field fields.Selector) generic.Matcher { if !ok { return nil, nil, fmt.Errorf("not a pod") } - return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), nil + + // podLabels is already sitting there ready to be used. + // podFields is not available directly and requires allocation of a map. + // Only bother if the fields might be useful to determining the match. + // One common case is for a replication controller to set up a watch + // based on labels alone; in that case we can avoid allocating the field map. + // This is especially important in the apiserver. + podLabels := labels.Set(pod.ObjectMeta.Labels) + var podFields fields.Set + if !field.Empty() && label.Matches(podLabels) { + podFields = PodToSelectableFields(pod) + } + return podLabels, podFields, nil }, } } diff --git a/pkg/storage/cacher.go b/pkg/storage/cacher.go index f246085545b..20acacc9a87 100644 --- a/pkg/storage/cacher.go +++ b/pkg/storage/cacher.go @@ -497,14 +497,39 @@ func (c *cacheWatcher) stop() { } } +var timerPool sync.Pool + func (c *cacheWatcher) add(event watchCacheEvent) { - t := time.NewTimer(5 * time.Second) - defer t.Stop() + // Try to send the event immediately, without blocking. select { case c.input <- event: + return + default: + } + + // OK, block sending, but only for up to 5 seconds. + // cacheWatcher.add is called very often, so arrange + // to reuse timers instead of constantly allocating. + const timeout = 5 * time.Second + t, ok := timerPool.Get().(*time.Timer) + if ok { + t.Reset(timeout) + } else { + t = time.NewTimer(timeout) + } + defer timerPool.Put(t) + + select { + case c.input <- event: + stopped := t.Stop() + if !stopped { + // Consume triggered (but not yet received) timer event + // so that future reuse does not get a spurious timeout. + <-t.C + } case <-t.C: // This means that we couldn't send event to that watcher. - // Since we don't want to blockin on it infinitely, + // Since we don't want to block on it infinitely, // we simply terminate it. c.forget(false) c.stop()