Skip to content

Commit

Permalink
test, benchmark and refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
koron committed Feb 15, 2024
1 parent 29180e5 commit 5af8db1
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 24 deletions.
11 changes: 10 additions & 1 deletion benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,18 @@ func BenchmarkEnqueue(b *testing.B) {

func BenchmarkDequeue(b *testing.B) {
rb := New[int](2 * 1024 * 1024)
rb.n = b.N
rb.n = len(rb.a)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = rb.Dequeue()
}
}

func BenchmarkPeek(b *testing.B) {
rb := New[int](2 * 1024 * 1024)
rb.n = len(rb.a)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = rb.Peek(i)
}
}
60 changes: 37 additions & 23 deletions ringbuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package ringbuf

// Buffer provides ring buffer.
type Buffer[T any] struct {
d []T
r int
n int
a []T
rx int
n int
}

// New creates a ring buffer with specified capacity.
Expand All @@ -13,18 +13,22 @@ func New[T any](capacity int) *Buffer[T] {
panic("capacity must be large than 0")
}
return &Buffer[T]{
d: make([]T, capacity),
a: make([]T, capacity),
}
}

// Enqueue puts a value to last of the buffer.
func (b *Buffer[T]) Enqueue(v T) {
b.d[(b.r+b.n)%len(b.d)] = v
if b.n < len(b.d) {
wx := b.rx + b.n
if wx >= len(b.a) {
wx -= len(b.a)
}
b.a[wx] = v
if b.n < len(b.a) {
b.n++
} else {
b.incR()
return
}
b.rxInc()
}

// Dequeue retrieves a value.
Expand All @@ -33,46 +37,56 @@ func (b *Buffer[T]) Dequeue() (T, bool) {
if b.n <= 0 {
return zero, false
}
v := b.d[b.r]
b.d[b.r] = zero
b.incR()
v := b.a[b.rx]
b.a[b.rx] = zero
b.rxInc()
b.n--
return v, true
}

// Clear remove all values.
func (b *Buffer[T]) Clear() {
var zero T
for b.n > 0 {
b.d[b.r] = zero
b.incR()
b.n--
for i := range b.a {
b.a[i] = zero
}
b.rx = 0
b.n = 0
}

// Empty checks the buffer is empty or not.
func (b *Buffer[T]) Empty() bool {
return b.n == 0
}

func (b *Buffer[T]) incR() int {
b.r++
if b.r == len(b.d) {
b.r = 0
// rxInc increments rx.
func (b *Buffer[T]) rxInc() int {
b.rx++
if b.rx == len(b.a) {
b.rx = 0
}
return b.r
return b.rx
}

// Cap returns capacity of the ringbuf.
func (b *Buffer[T]) Cap() int {
return len(b.a)
}

// Len returns number of valid items in the ringbuf
// Len returns number of valid items in the ringbuf.
func (b *Buffer[T]) Len() int {
return b.n
}

// Peek peeks a n'th value in ringbuf without removing.
// Peek peeks a n'th value in the ringbuf without removing.
func (b *Buffer[T]) Peek(n int) T {
var zero T
if n < 0 || n >= b.n {
return zero
}
return b.d[(b.r+n)%len(b.d)]
rx := b.rx + n
if rx >= len(b.a) {
rx -= len(b.a)
}
return b.a[rx]
}
6 changes: 6 additions & 0 deletions ringbuf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import "testing"
func TestRing(t *testing.T) {
check := func(n int, in []int, exp []int) {
b := New[int](n)
if cap := b.Cap(); cap != n {
t.Errorf("unexpectecd capacity: want=%d got=%d", n, cap)
}
for _, v := range in {
b.Enqueue(v)
}
Expand All @@ -23,6 +26,9 @@ func TestRing(t *testing.T) {
if ok {
t.Errorf("more value: w=%v n=%d in=%v", w, n, in)
}
if cap := b.Cap(); cap != n {
t.Errorf("unexpectecd capacity: want=%d got=%d", n, cap)
}
}

for _, d := range []struct {
Expand Down

0 comments on commit 5af8db1

Please sign in to comment.