From a37923439c8de016e329019102f0555c886c2fdd Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Sun, 3 Jun 2018 17:47:19 +0930 Subject: [PATCH] ring: add benchmark for roundtrip Running this on a RPi3 gives the following: ``` $ go test -run ^$ -bench . -benchmem -benchtime 30s goos: linux goarch: arm BenchmarkRoundTrip-4 2000 20178499 ns/op 1.49 MB/s 174 B/op 3 allocs/op PASS ``` --- ring/ring_test.go | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/ring/ring_test.go b/ring/ring_test.go index b607351b..7a556a30 100644 --- a/ring/ring_test.go +++ b/ring/ring_test.go @@ -205,3 +205,96 @@ func TestRoundTrip(t *testing.T) { wg.Wait() } } + +func BenchmarkRoundTrip(b *testing.B) { + const ( + maxTimeouts = 100 + + len = 50 + size = 150e3 + timeout = 10 * time.Millisecond + + frameLen = 30e3 + + writeDelay = 20 * time.Millisecond + readDelay = 50 * time.Millisecond + ) + + // Allocated prior to timer reset since it is an + // amortised cost. + rb := NewBuffer(len, size, timeout) + + // This is hoisted here to ensure the allocation + // is not counted since this is outside the control + // of the ring buffer. + buf := make([]byte, size+1) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + var timeouts int + elements: + for { + err := rb.Next(timeout) + switch err { + case nil: + timeouts = 0 + case ErrTimeout: + if timeouts > maxTimeouts { + b.Error("too many timeouts") + return + } + timeouts++ + case io.EOF: + break elements + default: + b.Errorf("unexpected read error: %v", err) + return + } + reads: + for { + n, err := rb.Read(buf) + if n != 0 { + time.Sleep(readDelay) // Simulate slow data processing. + } + switch err { + case nil: + case io.EOF: + break reads + default: + b.Errorf("unexpected read error: %v", err) + return + } + } + } + }() + + data := make([]byte, frameLen) + + b.ResetTimer() + b.SetBytes(frameLen) + + var dropped int + for i := 0; i < b.N; i++ { + time.Sleep(writeDelay) // Simulate slow data capture. + _, err := rb.Write(data) + switch err { + case nil: + dropped = 0 + case ErrDropped: + if dropped > maxTimeouts { + b.Error("too many write drops") + return + } + dropped++ + default: + b.Errorf("unexpected write error: %v", err) + return + } + } + + rb.Close() + + wg.Wait() +}