wgengine/magicsock: speed up BenchmarkReceiveFrom, store context.Done chan

context.cancelCtx.Done involves a mutex and isn't as cheap as I
previously assumed. Convert the donec method into a struct field and
store the channel value once. Our one magicsock.Conn gets one pointer
larger, but it cuts ~1% of the CPU time of the ReceiveFrom benchmark
and removes a bubble from the --svg output :)
This commit is contained in:
Brad Fitzpatrick 2021-01-15 19:13:59 -08:00
parent c78ed5b399
commit 4811236189
1 changed files with 9 additions and 9 deletions

View File

@ -128,6 +128,7 @@ type Conn struct {
connCtx context.Context // closed on Conn.Close
connCtxCancel func() // closes connCtx
donec <-chan struct{} // connCtx.Done()'s to avoid context.cancelCtx.Done()'s mutex per call
// pconn4 and pconn6 are the underlying UDP sockets used to
// send/receive packets for wireguard and other magicsock
@ -454,6 +455,7 @@ func NewConn(opts Options) (*Conn, error) {
}
c.connCtx, c.connCtxCancel = context.WithCancel(context.Background())
c.donec = c.connCtx.Done()
c.netChecker = &netcheck.Client{
Logf: logger.WithPrefix(c.logf, "netcheck: "),
GetSTUNConn4: func() netcheck.STUNConn { return c.pconn4 },
@ -486,8 +488,6 @@ func (c *Conn) Start() {
go c.periodicDerpCleanup()
}
func (c *Conn) donec() <-chan struct{} { return c.connCtx.Done() }
// ignoreSTUNPackets sets a STUN packet processing func that does nothing.
func (c *Conn) ignoreSTUNPackets() {
c.stunReceiveFunc.Store(func([]byte, netaddr.IPPort) {})
@ -1099,7 +1099,7 @@ func (c *Conn) sendAddr(addr netaddr.IPPort, pubKey key.Public, b []byte) (sent
copy(pkt, b)
select {
case <-c.donec():
case <-c.donec:
return false, errConnClosed
case ch <- derpWriteRequest{addr, pubKey, pkt}:
return true, nil
@ -1468,7 +1468,7 @@ func (c *Conn) awaitUDP4(b []byte) {
if err != nil {
select {
case c.udpRecvCh <- udpReadResult{err: err}:
case <-c.donec():
case <-c.donec:
}
return
}
@ -1487,7 +1487,7 @@ func (c *Conn) awaitUDP4(b []byte) {
select {
case c.udpRecvCh <- udpReadResult{n: n, addr: addr, ipp: ipp}:
case <-c.donec():
case <-c.donec:
}
return
}
@ -1548,7 +1548,7 @@ Top:
c.bufferedIPv4Packet = append(c.bufferedIPv4Packet[:0], b[:um.n]...)
}
c.pconn4.SetReadDeadline(time.Time{})
case <-c.donec():
case <-c.donec:
return 0, nil, errors.New("Conn closed")
}
var regionID int
@ -1627,7 +1627,7 @@ Top:
c.noteRecvActivityFromEndpoint(ep)
return n, ep, nil
case <-c.donec():
case <-c.donec:
// Socket has been shut down. All the producers of packets
// respond to the context cancellation and go away, so we have
// to also unblock and return an error, to inform wireguard-go
@ -2362,7 +2362,7 @@ func (c *Conn) periodicReSTUN() {
var lastIdleState opt.Bool
for {
select {
case <-c.donec():
case <-c.donec:
return
case <-timer.C:
doReSTUN := c.shouldDoPeriodicReSTUN()
@ -2387,7 +2387,7 @@ func (c *Conn) periodicDerpCleanup() {
defer ticker.Stop()
for {
select {
case <-c.donec():
case <-c.donec:
return
case <-ticker.C:
c.cleanStaleDerp()