wgengine/userspace: reduce allocations in getStatus
Two optimizations. Use values instead of pointers. We were using pointers to make track the "peer in progress" easier. It's not too hard to do it manually, though. Make two passes through the data, so that we can size our return value accurately from the beginning. This is cheap enough compared to the allocation, which grows linearly in the number of peers, that it is worth doing. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
af30897f0d
commit
adf696172d
|
@ -921,8 +921,8 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
|
|||
errc <- err
|
||||
}()
|
||||
|
||||
pp := make(map[wgkey.Key]*ipnstate.PeerStatusLite)
|
||||
p := &ipnstate.PeerStatusLite{}
|
||||
pp := make(map[wgkey.Key]ipnstate.PeerStatusLite)
|
||||
var p ipnstate.PeerStatusLite
|
||||
|
||||
var hst1, hst2, n int64
|
||||
|
||||
|
@ -954,11 +954,10 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("IpcGetOperation: invalid key in line %q", line)
|
||||
}
|
||||
p = &ipnstate.PeerStatusLite{}
|
||||
pp[wgkey.Key(pk)] = p
|
||||
|
||||
key := tailcfg.NodeKey(pk)
|
||||
p.NodeKey = key
|
||||
if !p.NodeKey.IsZero() {
|
||||
pp[wgkey.Key(p.NodeKey)] = p
|
||||
}
|
||||
p = ipnstate.PeerStatusLite{NodeKey: tailcfg.NodeKey(pk)}
|
||||
case "rx_bytes":
|
||||
n, err = mem.ParseInt(v, 10, 64)
|
||||
p.RxBytes = n
|
||||
|
@ -986,6 +985,9 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
|
|||
} // else leave at time.IsZero()
|
||||
}
|
||||
}
|
||||
if !p.NodeKey.IsZero() {
|
||||
pp[wgkey.Key(p.NodeKey)] = p
|
||||
}
|
||||
if err := <-errc; err != nil {
|
||||
return nil, fmt.Errorf("IpcGetOperation: %v", err)
|
||||
}
|
||||
|
@ -993,10 +995,19 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
|
|||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
var peers []ipnstate.PeerStatusLite
|
||||
// Do two passes, one to calculate size and the other to populate.
|
||||
// This code is sensitive to allocations.
|
||||
npeers := 0
|
||||
for _, pk := range e.peerSequence {
|
||||
if _, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config
|
||||
npeers++
|
||||
}
|
||||
}
|
||||
|
||||
peers := make([]ipnstate.PeerStatusLite, 0, npeers)
|
||||
for _, pk := range e.peerSequence {
|
||||
if p, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config
|
||||
peers = append(peers, *p)
|
||||
peers = append(peers, p)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue