device: add latency and throughput benchmarks
These obviously don't perfectly capture real world performance, in which syscalls and network links have a significant impact. Nevertheless, they capture some of the internal performance factors, and they're easy and convenient to work with. Hat tip to Avery Pennarun for help designing the throughput benchmark. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
8a30415555
commit
85b4950579
|
@ -12,6 +12,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -281,3 +282,61 @@ func randDevice(t *testing.T) *Device {
|
||||||
device.SetPrivateKey(sk)
|
device.SetPrivateKey(sk)
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkLatency(b *testing.B) {
|
||||||
|
pair := genTestPair(b)
|
||||||
|
|
||||||
|
// Establish a connection.
|
||||||
|
pair.Send(b, Ping, nil)
|
||||||
|
pair.Send(b, Pong, nil)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
pair.Send(b, Ping, nil)
|
||||||
|
pair.Send(b, Pong, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkThroughput(b *testing.B) {
|
||||||
|
pair := genTestPair(b)
|
||||||
|
|
||||||
|
// Establish a connection.
|
||||||
|
pair.Send(b, Ping, nil)
|
||||||
|
pair.Send(b, Pong, nil)
|
||||||
|
|
||||||
|
// Measure how long it takes to receive b.N packets,
|
||||||
|
// starting when we receive the first packet.
|
||||||
|
var recv uint64
|
||||||
|
var elapsed time.Duration
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
var start time.Time
|
||||||
|
for {
|
||||||
|
<-pair[0].tun.Inbound
|
||||||
|
new := atomic.AddUint64(&recv, 1)
|
||||||
|
if new == 1 {
|
||||||
|
start = time.Now()
|
||||||
|
}
|
||||||
|
// Careful! Don't change this to else if; b.N can be equal to 1.
|
||||||
|
if new == uint64(b.N) {
|
||||||
|
elapsed = time.Since(start)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Send packets as fast as we can until we've received enough.
|
||||||
|
ping := tuntest.Ping(pair[0].ip, pair[1].ip)
|
||||||
|
pingc := pair[1].tun.Outbound
|
||||||
|
var sent uint64
|
||||||
|
for atomic.LoadUint64(&recv) != uint64(b.N) {
|
||||||
|
sent++
|
||||||
|
pingc <- ping
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
b.ReportMetric(float64(elapsed)/float64(b.N), "ns/op")
|
||||||
|
b.ReportMetric(1-float64(b.N)/float64(sent), "packet-loss")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue