aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Miek Gieben <miek@miek.nl> 2019-10-03 15:05:44 +0100
committerGravatar GitHub <noreply@github.com> 2019-10-03 15:05:44 +0100
commitf8551df27284b93e9f95e064ec65a9df60f4a528 (patch)
treee7d70ac9ede0ad2e37b0d9753bd900c41fb371ee
parentaa96d6b443ea58c8f7c80649f76b93e243fbb3f4 (diff)
downloadcoredns-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.go45
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" }