diff options
| author | Josh Bleecher Snyder <josh@tailscale.com> | 2020-12-08 13:42:48 -0800 |
|---|---|---|
| committer | Josh Bleecher Snyder <josh@tailscale.com> | 2020-12-08 13:42:48 -0800 |
| commit | ab637ea4970cf08e0bdb09bc05b06b2b776bc9c7 (patch) | |
| tree | 5c0fe17a06a6a886fdbd330720bf6ab0bc345d0d | |
| parent | 9503be083ddaa72d208be1fbbd3bab1a5cd80c91 (diff) | |
| download | tailscale-josh/no-goroutine-per-udp-read-2.tar.xz tailscale-josh/no-goroutine-per-udp-read-2.zip | |
try a stupider way to have one goroutine per udp read (doesn't work)josh/no-goroutine-per-udp-read-2
name old time/op new time/op delta
ReceiveFrom-8 16.8µs ±29% 22.8µs ±11% +35.22% (p=0.000 n=10+10)
ReceiveFrom_Native-8 19.1µs ±11% 20.6µs ± 9% +8.03% (p=0.009 n=10+10)
name old alloc/op new alloc/op delta
ReceiveFrom-8 112B ± 0% 112B ± 0% ~ (all equal)
ReceiveFrom_Native-8 112B ± 0% 112B ± 0% ~ (all equal)
name old allocs/op new allocs/op delta
ReceiveFrom-8 3.00 ± 0% 3.00 ± 0% ~ (all equal)
ReceiveFrom_Native-8 3.00 ± 0% 3.00 ± 0% ~ (all equal)
| -rw-r--r-- | wgengine/magicsock/magicsock.go | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 15af3326b..6d17734b4 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -141,6 +141,9 @@ type Conn struct { // packetListener optionally specifies a test hook to open a PacketConn. packetListener nettype.PacketListener + awaitOnce sync.Once + awaitBufC chan []byte + // ============================================================ mu sync.Mutex // guards all following fields; see userspaceEngine lock ordering rules muCond *sync.Cond @@ -1498,9 +1501,15 @@ type udpReadResult struct { // immediate cancellation of network operations. var aLongTimeAgo = time.Unix(233431200, 0) +func (c *Conn) awaitUDP4() { + for b := range c.awaitBufC { + c.awaitUDP4one(b) + } +} + // awaitUDP4 reads a single IPv4 UDP packet (or an error) and sends it // to c.udpRecvCh, skipping over (but handling) any STUN replies. -func (c *Conn) awaitUDP4(b []byte) { +func (c *Conn) awaitUDP4one(b []byte) { for { n, pAddr, err := c.pconn4.ReadFrom(b) if err != nil { @@ -1571,7 +1580,11 @@ Top: return copy(b, c.bufferedIPv4Packet), ep, wgRecvAddr(ep, from, addr), nil } - go c.awaitUDP4(b) + c.awaitOnce.Do(func() { + c.awaitBufC = make(chan []byte) + go c.awaitUDP4() + }) + c.awaitBufC <- b // Once the above goroutine has started, it owns b until it writes // to udpRecvCh. The code below must not access b until it's @@ -2324,6 +2337,9 @@ func (c *Conn) Close() error { for c.goroutinesRunningLocked() { c.muCond.Wait() } + + close(c.awaitBufC) + // TODO: stop awaitUDP4 goroutine return err } |
