summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josh@tailscale.com>2020-12-08 13:42:48 -0800
committerJosh Bleecher Snyder <josh@tailscale.com>2020-12-08 13:42:48 -0800
commitab637ea4970cf08e0bdb09bc05b06b2b776bc9c7 (patch)
tree5c0fe17a06a6a886fdbd330720bf6ab0bc345d0d
parent9503be083ddaa72d208be1fbbd3bab1a5cd80c91 (diff)
downloadtailscale-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.go20
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
}