mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-16 19:49:56 +00:00
#6412 put PeerStateByIP (one read per private-service request / DNS answer) onto the status recorder lock and switched that lock from sync.Mutex to sync.RWMutex. The RWMutex wins a clean microbenchmark, but on a busy client bringing up ~1000 peers the steady data-path read flood plus a slow lock holder (a relay handshake under GetRelayStates, a 1000-peer FullStats dump under RefreshWireGuardStats, or an ordinary GetFullStatus poll) starves the connect-side writes: Go's RWMutex does not protect a writer from a continuous stream of readers, so peer state transitions stall and peers fail to connect. Revert d.mux to sync.Mutex, whose starvation-prevention handoff keeps writes fair. The lost read parallelism is not a bottleneck at this scale. Add status_contention_test.go, which reproduces the scenario and includes a regression guard (TestStatusRecorderContention) that fails if the connect-side write path regresses toward the starving RWMutex behaviour. Real recorder, same workload, lock type as the only variable: lock writes(connect) write-p99 write-p999 write-max RWMutex ~22,000 10.4ms 96ms 131ms (guard FAILS) Mutex ~97,000 4.4ms 7.7ms 14.6ms (guard passes)