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
```
This commit is contained in:
Dan Kortschak 2018-06-03 17:47:19 +09:30
parent 2791939f34
commit a37923439c
1 changed files with 93 additions and 0 deletions

View File

@ -205,3 +205,96 @@ func TestRoundTrip(t *testing.T) {
wg.Wait() 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()
}