Compare commits

...

2 Commits

Author SHA1 Message Date
Josh Bleecher Snyder
74dccdf7a0 optimize: calc size, use values 2021-08-06 15:41:28 -07:00
Josh Bleecher Snyder
6a93463952 move code around, add benchmark
note that this splits a mutex access in two
2021-08-06 15:30:59 -07:00
2 changed files with 108 additions and 20 deletions

View File

@@ -921,11 +921,6 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
errc <- err
}()
pp := make(map[wgkey.Key]*ipnstate.PeerStatusLite)
p := &ipnstate.PeerStatusLite{}
var hst1, hst2, n int64
br := e.statusBufioReader
if br != nil {
br.Reset(pr)
@@ -933,6 +928,29 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
br = bufio.NewReaderSize(pr, 1<<10)
e.statusBufioReader = br
}
peers, err := e.getPeerStatusLite(br)
if err != nil {
return nil, err
}
if err := <-errc; err != nil {
return nil, fmt.Errorf("IpcGetOperation: %v", err)
}
e.mu.Lock()
defer e.mu.Unlock()
return &Status{
LocalAddrs: append([]tailcfg.Endpoint(nil), e.endpoints...),
Peers: peers,
DERPs: derpConns,
}, nil
}
func (e *userspaceEngine) getPeerStatusLite(br *bufio.Reader) ([]ipnstate.PeerStatusLite, error) {
pp := make(map[wgkey.Key]ipnstate.PeerStatusLite)
var p ipnstate.PeerStatusLite
var hst1, hst2, n int64
for {
line, err := br.ReadSlice('\n')
if err == io.EOF {
@@ -954,11 +972,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,25 +1003,29 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
} // else leave at time.IsZero()
}
}
if err := <-errc; err != nil {
return nil, fmt.Errorf("IpcGetOperation: %v", err)
if !p.NodeKey.IsZero() {
pp[wgkey.Key(p.NodeKey)] = p
}
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 p, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config
peers = append(peers, *p)
if _, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config
npeers++
}
}
return &Status{
LocalAddrs: append([]tailcfg.Endpoint(nil), e.endpoints...),
Peers: peers,
DERPs: derpConns,
}, nil
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)
}
}
return peers, nil
}
func (e *userspaceEngine) RequestStatus() {

View File

@@ -5,9 +5,11 @@
package wgengine
import (
"bufio"
"bytes"
"fmt"
"reflect"
"strings"
"testing"
"go4.org/mem"
@@ -17,6 +19,7 @@ import (
"tailscale.com/tailcfg"
"tailscale.com/tstime/mono"
"tailscale.com/types/key"
"tailscale.com/types/wgkey"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/wgcfg"
)
@@ -252,3 +255,67 @@ func BenchmarkGenLocalAddrFunc(b *testing.B) {
})
b.Logf("x = %v", x)
}
func BenchmarkGetPeerStatusLite(b *testing.B) {
e := new(userspaceEngine)
br := bufio.NewReaderSize(nil, 1<<10)
parseKey := func(s string) wgkey.Key {
k, err := wgkey.ParseHex(s)
if err != nil {
b.Fatal(err)
}
return k
}
e.peerSequence = []wgkey.Key{
parseKey("0000000000000000000000000000000000000000000000000000000000000002"),
parseKey("0000000000000000000000000000000000000000000000000000000000000003"),
parseKey("0000000000000000000000000000000000000000000000000000000000000004"),
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
br.Reset(strings.NewReader(sampleStatus))
_, err := e.getPeerStatusLite(br)
if err != nil {
b.Fatal(err)
}
}
}
const sampleStatus = `
private_key=0000000000000000000000000000000000000000000000000000000000000001
listen_port=50818
public_key=0000000000000000000000000000000000000000000000000000000000000002
preshared_key=0000000000000000000000000000000000000000000000000000000000000000
protocol_version=1
endpoint={"pk":"0000000000000000000000000000000000000000000000000000000000000002","dk":"discokey:0000000000000000000000000000000000000000000000000000000000000000","ipp":["139.162.81.125:41641"]}
last_handshake_time_sec=1628288511
last_handshake_time_nsec=993469000
tx_bytes=272
rx_bytes=272
persistent_keepalive_interval=25
allowed_ip=100.100.100.101/32
allowed_ip=::2/128
public_key=0000000000000000000000000000000000000000000000000000000000000003
preshared_key=0000000000000000000000000000000000000000000000000000000000000000
protocol_version=1
endpoint={"pk":"0000000000000000000000000000000000000000000000000000000000000003","dk":"discokey:c6c0a1488ac6cb9e0103d056ca51387e33513d577b985e77c6ea075f76b27d35","ipp":null}
last_handshake_time_sec=1628288511
last_handshake_time_nsec=615842000
tx_bytes=1300
rx_bytes=92
persistent_keepalive_interval=0
allowed_ip=100.100.100.102/32
allowed_ip=::3/128
public_key=0000000000000000000000000000000000000000000000000000000000000004
preshared_key=0000000000000000000000000000000000000000000000000000000000000000
protocol_version=1
endpoint={"pk":"0000000000000000000000000000000000000000000000000000000000000004","dk":"discokey:c6c0a1488ac6cb9e0103d056ca51387e33513d577b985e77c6ea075f76b27d35","ipp":null}
last_handshake_time_sec=1628288511
last_handshake_time_nsec=615842000
tx_bytes=1300
rx_bytes=92
persistent_keepalive_interval=0
allowed_ip=100.100.100.103/32
allowed_ip=::4/128
`