From a308261a76e95807650fbad95accc7374ba793fb Mon Sep 17 00:00:00 2001 From: Staon Date: Fri, 4 Dec 2020 10:37:10 +0100 Subject: [PATCH] Remove doubling of memory in the Clear method (#96) 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 --- ringbuf.go | 10 ++++++++- ringbuf_test.go | 54 +++++++++++++++++++++++++++---------------------- segment.go | 2 +- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/ringbuf.go b/ringbuf.go index 7fac053..71e3586 100644 --- a/ringbuf.go +++ b/ringbuf.go @@ -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. diff --git a/ringbuf_test.go b/ringbuf_test.go index 0e7f7e8..a01b25e 100644 --- a/ringbuf_test.go +++ b/ringbuf_test.go @@ -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) } } diff --git a/segment.go b/segment.go index be113f9..9ebea9b 100644 --- a/segment.go +++ b/segment.go @@ -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)