// Copyright (c) Tailscale Inc & AUTHORS // SPDX-License-Identifier: BSD-3-Clause // Create two wgengine instances and pass data through them, measuring // throughput, latency, and packet loss. package main import ( "fmt" "testing" "time" "tailscale.com/types/logger" ) func BenchmarkTrivialNoAlloc(b *testing.B) { run(b, setupTrivialNoAllocTest) } func BenchmarkTrivial(b *testing.B) { run(b, setupTrivialTest) } func BenchmarkBlockingChannel(b *testing.B) { run(b, setupBlockingChannelTest) } func BenchmarkNonblockingChannel(b *testing.B) { run(b, setupNonblockingChannelTest) } func BenchmarkDoubleChannel(b *testing.B) { run(b, setupDoubleChannelTest) } func BenchmarkUDP(b *testing.B) { run(b, setupUDPTest) } func BenchmarkBatchTCP(b *testing.B) { run(b, setupBatchTCPTest) } func BenchmarkWireGuardTest(b *testing.B) { b.Skip("https://github.com/tailscale/tailscale/issues/2716") run(b, func(logf logger.Logf, traf *TrafficGen) { setupWGTest(b, logf, traf, Addr1, Addr2) }) } type SetupFunc func(logger.Logf, *TrafficGen) func run(b *testing.B, setup SetupFunc) { sizes := []int{ ICMPMinSize + 8, ICMPMinSize + 100, ICMPMinSize + 1000, } for _, size := range sizes { b.Run(fmt.Sprintf("%d", size), func(b *testing.B) { runOnce(b, setup, size) }) } } func runOnce(b *testing.B, setup SetupFunc, payload int) { b.StopTimer() b.ReportAllocs() var logf logger.Logf = b.Logf if !testing.Verbose() { logf = logger.Discard } traf := NewTrafficGen(b.StartTimer) setup(logf, traf) logf("initialized. (n=%v)", b.N) b.SetBytes(int64(payload)) traf.Start(Addr1.Addr(), Addr2.Addr(), payload, int64(b.N)) var cur, prev Snapshot var pps int64 i := 0 for traf.Running() { i += 1 time.Sleep(10 * time.Millisecond) if (i % 100) == 0 { prev = cur cur = traf.Snap() d := cur.Sub(prev) if prev.WhenNsec != 0 { logf("%v @%7d pkt/sec", d, pps) } } pps = traf.Adjust() } cur = traf.Snap() d := cur.Sub(prev) loss := float64(d.LostPackets) / float64(d.RxPackets) b.ReportMetric(loss*100, "%lost") }