mirror of
https://github.com/coredns/coredns.git
synced 2025-11-25 13:14:02 -05:00
perf(proxy): avoid unnecessary alloc in Yield (#7708)
This commit is contained in:
@@ -128,9 +128,15 @@ const yieldTimeout = 25 * time.Millisecond
|
|||||||
func (t *Transport) Yield(pc *persistConn) {
|
func (t *Transport) Yield(pc *persistConn) {
|
||||||
pc.used = time.Now() // update used time
|
pc.used = time.Now() // update used time
|
||||||
|
|
||||||
// Make this non-blocking, because in the case of a very busy forwarder we will *block* on this yield. This
|
// Optimization: Try to return the connection immediately without creating a timer.
|
||||||
// blocks the outer go-routine and stuff will just pile up. We timeout when the send fails to as returning
|
// If the receiver is not ready, we fall back to a timeout-based send to avoid blocking forever.
|
||||||
// these connection is an optimization anyway.
|
// Returning the connection is just an optimization, so dropping it on timeout is fine.
|
||||||
|
select {
|
||||||
|
case t.yield <- pc:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case t.yield <- pc:
|
case t.yield <- pc:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -107,3 +108,31 @@ func TestCleanupAll(t *testing.T) {
|
|||||||
t.Error("Expected no cached connections")
|
t.Error("Expected no cached connections")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkYield(b *testing.B) {
|
||||||
|
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
||||||
|
ret := new(dns.Msg)
|
||||||
|
ret.SetReply(r)
|
||||||
|
w.WriteMsg(ret)
|
||||||
|
})
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
tr := newTransport("BenchmarkYield", s.Addr)
|
||||||
|
tr.Start()
|
||||||
|
defer tr.Stop()
|
||||||
|
|
||||||
|
c, _, _ := tr.Dial("udp")
|
||||||
|
|
||||||
|
b.ReportAllocs()
|
||||||
|
|
||||||
|
for b.Loop() {
|
||||||
|
tr.Yield(c)
|
||||||
|
// Drain the yield channel so we can yield again without blocking/timing out
|
||||||
|
// We need to simulate the consumer side slightly to keep Yield flowing
|
||||||
|
select {
|
||||||
|
case <-tr.yield:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
runtime.Gosched()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user