Skip to content

Commit

Permalink
Remove doubling of memory in the Clear method (#96)
Browse files Browse the repository at this point in the history
Previous implementation of the Clear method has allocated new ringbuffers.
Memory footprint of the process has been doubled so as the old memory blocks
stayed in the memory until the garbage collector cleaned them.

This change In this commit the the beahvior has been changed: just internal
pointers in the ringbuffers are reset now and the old memory blocks are reused.

Co-authored-by: Ondrej Starek <[email protected]>
  • Loading branch information
Staon and Ondrej Starek authored Dec 4, 2020
1 parent a70daa2 commit a308261
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
10 changes: 9 additions & 1 deletion ringbuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ type RingBuf struct {

func NewRingBuf(size int, begin int64) (rb RingBuf) {
rb.data = make([]byte, size)
rb.Reset(begin)
return
}

// Reset the ring buffer
//
// Parameters:
// begin: beginning offset of the data stream
func (rb *RingBuf) Reset(begin int64) {
rb.begin = begin
rb.end = begin
rb.index = 0
return
}

// Create a copy of the buffer.
Expand Down
54 changes: 30 additions & 24 deletions ringbuf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,36 @@ import (

func TestRingBuf(t *testing.T) {
rb := NewRingBuf(16, 0)
rb.Write([]byte("fghibbbbccccddde"))
rb.Write([]byte("fghibbbbc"))
rb.Resize(16)
off := rb.Evacuate(9, 3)
t.Log(string(rb.Dump()))
if off != rb.End()-3 {
t.Log(string(rb.Dump()), rb.End())
t.Fatalf("off got %v", off)
}
off = rb.Evacuate(15, 5)
t.Log(string(rb.Dump()))
if off != rb.End()-5 {
t.Fatalf("off got %v", off)
}
rb.Resize(64)
rb.Resize(32)
data := make([]byte, 5)
rb.ReadAt(data, off)
if string(data) != "efghi" {
t.Fatalf("read at should be efghi, got %v", string(data))
}
for i := 0; i < 2; i++ {
rb.Write([]byte("fghibbbbccccddde"))
rb.Write([]byte("fghibbbbc"))
rb.Resize(16)
off := rb.Evacuate(9, 3)
t.Log(string(rb.Dump()))
if off != rb.End()-3 {
t.Log(string(rb.Dump()), rb.End())
t.Fatalf("off got %v", off)
}
off = rb.Evacuate(15, 5)
t.Log(string(rb.Dump()))
if off != rb.End()-5 {
t.Fatalf("off got %v", off)
}
rb.Resize(64)
rb.Resize(32)
data := make([]byte, 5)
rb.ReadAt(data, off)
if string(data) != "efghi" {
t.Fatalf("read at should be efghi, got %v", string(data))
}

off = rb.Evacuate(0, 10)
if off != -1 {
t.Fatal("evacutate out of range offset should return error")
}

off = rb.Evacuate(0, 10)
if off != -1 {
t.Fatal("evacutate out of range offset should return error")
/* -- After reset the buffer should behave exactly the same as a new one.
* Hence, run the test once more again with reset buffer. */
rb.Reset(0)
}
}
2 changes: 1 addition & 1 deletion segment.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ func (seg *segment) resetStatistics() {

func (seg *segment) clear() {
bufSize := len(seg.rb.data)
seg.rb = NewRingBuf(bufSize, 0)
seg.rb.Reset(0)
seg.vacuumLen = int64(bufSize)
seg.slotCap = 1
seg.slotsData = make([]entryPtr, 256*seg.slotCap)
Expand Down

0 comments on commit a308261

Please sign in to comment.