diff options
author | 2019-10-03 15:05:44 +0100 | |
---|---|---|
committer | 2019-10-03 15:05:44 +0100 | |
commit | f8551df27284b93e9f95e064ec65a9df60f4a528 (patch) | |
tree | e7d70ac9ede0ad2e37b0d9753bd900c41fb371ee | |
parent | aa96d6b443ea58c8f7c80649f76b93e243fbb3f4 (diff) | |
download | coredns-f8551df27284b93e9f95e064ec65a9df60f4a528.tar.gz coredns-f8551df27284b93e9f95e064ec65a9df60f4a528.tar.zst coredns-f8551df27284b93e9f95e064ec65a9df60f4a528.zip |
cache: move goroutine closure to separate function to save memory (#3353)
The goroutine closure was causing objects to be heap allocated. Moving
it to a separate function fixes that.
```benchmark old ns/op new ns/op delta
BenchmarkCacheResponse/NoPrefetch-12 773 713 -7.76%
BenchmarkCacheResponse/Prefetch-12 878 837 -4.67%
BenchmarkHash-12 9.17 9.18 +0.11%
benchmark old allocs new allocs delta
BenchmarkCacheResponse/NoPrefetch-12 9 8 -11.11%
BenchmarkCacheResponse/Prefetch-12 9 8 -11.11%
BenchmarkHash-12 0 0 +0.00%
benchmark old bytes new bytes delta
BenchmarkCacheResponse/NoPrefetch-12 471 327 -30.57%
BenchmarkCacheResponse/Prefetch-12 471 327 -30.57%
BenchmarkHash-12 0 0 +0.00%
```
Signed-off-by: Charlie Vieth <charlie.vieth@gmail.com>
Signed-off-by: Miek Gieben <miek@miek.nl>
-rw-r--r-- | plugin/cache/handler.go | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/plugin/cache/handler.go b/plugin/cache/handler.go index 2d608e8d3..4dc29167a 100644 --- a/plugin/cache/handler.go +++ b/plugin/cache/handler.go @@ -29,28 +29,10 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) i, found := c.get(now, state, server) if i != nil && found { resp := i.toMsg(r, now) - w.WriteMsg(resp) - if c.prefetch > 0 { - ttl := i.ttl(now) - i.Freq.Update(c.duration, now) - - threshold := int(math.Ceil(float64(c.percentage) / 100 * float64(i.origTTL))) - if i.Freq.Hits() >= c.prefetch && ttl <= threshold { - cw := newPrefetchResponseWriter(server, state, c) - go func(w dns.ResponseWriter) { - cachePrefetches.WithLabelValues(server).Inc() - plugin.NextOrFailure(c.Name(), c.Next, ctx, w, r) - - // When prefetching we loose the item i, and with it the frequency - // that we've gathered sofar. See we copy the frequencies info back - // into the new item that was stored in the cache. - if i1 := c.exists(state); i1 != nil { - i1.Freq.Reset(now, i.Freq.Hits()) - } - }(cw) - } + if c.shouldPrefetch(i, now) { + go c.doPrefetch(ctx, state, server, i, now) } return dns.RcodeSuccess, nil } @@ -59,6 +41,29 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) return plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r) } +func (c *Cache) doPrefetch(ctx context.Context, state request.Request, server string, i *item, now time.Time) { + cw := newPrefetchResponseWriter(server, state, c) + + cachePrefetches.WithLabelValues(server).Inc() + plugin.NextOrFailure(c.Name(), c.Next, ctx, cw, state.Req) + + // When prefetching we loose the item i, and with it the frequency + // that we've gathered sofar. See we copy the frequencies info back + // into the new item that was stored in the cache. + if i1 := c.exists(state); i1 != nil { + i1.Freq.Reset(now, i.Freq.Hits()) + } +} + +func (c *Cache) shouldPrefetch(i *item, now time.Time) bool { + if c.prefetch <= 0 { + return false + } + i.Freq.Update(c.duration, now) + threshold := int(math.Ceil(float64(c.percentage) / 100 * float64(i.origTTL))) + return i.Freq.Hits() >= c.prefetch && i.ttl(now) <= threshold +} + // Name implements the Handler interface. func (c *Cache) Name() string { return "cache" } |