Преглед изворни кода

wgengine: use a singleflight.Group to reduce status contention (#5450)

Updates tailscale/coral#72

Signed-off-by: Andrew Dunham <[email protected]>

Signed-off-by: Andrew Dunham <[email protected]>
Andrew Dunham пре 3 година
родитељ
комит
e8f09d24c7
2 измењених фајлова са 15 додато и 1 уклоњено
  1. 10 1
      wgengine/pendopen.go
  2. 5 0
      wgengine/userspace.go

+ 10 - 1
wgengine/pendopen.go

@@ -157,12 +157,21 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) {
 		return
 	}
 
+	// We don't care if this information is perfectly up-to-date, since
+	// we're just using it to print debug information.
+	//
+	// In tailscale/coral#72, we see a goroutine profile with thousands of
+	// goroutines blocked on the mutex in getStatus here, so we wrap it in
+	// a singleflight and accept stale information to reduce contention.
+	st, err, _ := e.getStatusSf.Do(struct{}{}, e.getStatus)
+
 	var ps *ipnstate.PeerStatusLite
-	if st, err := e.getStatus(); err == nil {
+	if err == nil {
 		for _, v := range st.Peers {
 			if v.NodeKey == n.Key {
 				v := v // copy
 				ps = &v
+				break
 			}
 		}
 	} else {

+ 5 - 0
wgengine/userspace.go

@@ -46,6 +46,7 @@ import (
 	"tailscale.com/util/clientmetric"
 	"tailscale.com/util/deephash"
 	"tailscale.com/util/mak"
+	"tailscale.com/util/singleflight"
 	"tailscale.com/version"
 	"tailscale.com/wgengine/filter"
 	"tailscale.com/wgengine/magicsock"
@@ -146,6 +147,10 @@ type userspaceEngine struct {
 	// value of the ICMP identifer and sequence number concatenated.
 	icmpEchoResponseCallback map[uint32]func()
 
+	// this singleflight is used to deduplicate calls to getStatus when we
+	// don't care if the data is perfectly fresh
+	getStatusSf singleflight.Group[struct{}, *Status]
+
 	// Lock ordering: magicsock.Conn.mu, wgLock, then mu.
 }