Skip to content
This repository was archived by the owner on Jul 31, 2023. It is now read-only.

Commit c04732d

Browse files
cakiecakieIan Miao
authored andcommitted
Fix evictedQueue memory leak
1 parent 46dfec7 commit c04732d

File tree

3 files changed

+82
-55
lines changed

3 files changed

+82
-55
lines changed

trace/evictedqueue.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,45 @@
1515
package trace
1616

1717
type evictedQueue struct {
18-
queue []interface{}
18+
ringQueue []interface{}
1919
capacity int
2020
droppedCount int
21+
writeIdx int
22+
readIdx int
23+
startRead bool
2124
}
2225

2326
func newEvictedQueue(capacity int) *evictedQueue {
2427
eq := &evictedQueue{
25-
capacity: capacity,
26-
queue: make([]interface{}, 0),
28+
capacity: capacity,
29+
ringQueue: make([]interface{}, 0),
2730
}
2831

2932
return eq
3033
}
3134

3235
func (eq *evictedQueue) add(value interface{}) {
33-
if len(eq.queue) == eq.capacity {
34-
eq.queue = eq.queue[1:]
35-
eq.droppedCount++
36+
if len(eq.ringQueue) < eq.capacity {
37+
eq.ringQueue = append(eq.ringQueue, value)
38+
return
3639
}
37-
eq.queue = append(eq.queue, value)
40+
41+
eq.ringQueue[eq.writeIdx] = value
42+
eq.droppedCount++
43+
eq.writeIdx++
44+
eq.writeIdx %= eq.capacity
45+
eq.readIdx = eq.writeIdx
46+
}
47+
48+
// Do not add more item after use readNext
49+
func (eq *evictedQueue) readNext() interface{} {
50+
if eq.startRead && eq.readIdx == eq.writeIdx {
51+
return nil
52+
}
53+
54+
eq.startRead = true
55+
res := eq.ringQueue[eq.readIdx]
56+
eq.readIdx++
57+
eq.readIdx %= eq.capacity
58+
return res
3859
}

trace/evictedqueue_test.go

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -15,51 +15,57 @@
1515
package trace
1616

1717
import (
18+
"fmt"
1819
"reflect"
1920
"testing"
2021
)
2122

2223
func init() {
2324
}
2425

25-
func TestAdd(t *testing.T) {
26-
q := newEvictedQueue(3)
27-
q.add("value1")
28-
q.add("value2")
29-
if wantLen, gotLen := 2, len(q.queue); wantLen != gotLen {
30-
t.Errorf("got queue length %d want %d", gotLen, wantLen)
31-
}
32-
}
26+
func TestAddAndReadNext(t *testing.T) {
27+
t.Run("len(ringQueue) < capacity", func(t *testing.T) {
28+
values := []string{"value1", "value2"}
29+
capacity := 3
30+
q := newEvictedQueue(capacity)
3331

34-
func (eq *evictedQueue) queueToArray() []string {
35-
arr := make([]string, 0)
36-
for _, value := range eq.queue {
37-
arr = append(arr, value.(string))
38-
}
39-
return arr
40-
}
32+
for _, value := range values {
33+
q.add(value)
34+
}
35+
36+
gotValues := make([]string, len(q.ringQueue))
37+
for i := 0; i < len(gotValues); i++ {
38+
gotValues[i] = q.readNext().(string)
39+
}
40+
41+
if !reflect.DeepEqual(values, gotValues) {
42+
t.Errorf("got array = %#v; want %#v", gotValues, values)
43+
}
44+
})
45+
t.Run("dropped count", func(t *testing.T) {
46+
values := []string{"value1", "value2", "value3", "value1", "value4", "value1", "value3", "value1", "value4"}
47+
wantValues := []string{"value3", "value1", "value4"}
48+
capacity := 3
49+
wantDroppedCount := len(values) - capacity
50+
51+
q := newEvictedQueue(capacity)
52+
53+
for _, value := range values {
54+
q.add(value)
55+
fmt.Println(q.ringQueue)
56+
}
4157

42-
func TestDropCount(t *testing.T) {
43-
q := newEvictedQueue(3)
44-
q.add("value1")
45-
q.add("value2")
46-
q.add("value3")
47-
q.add("value1")
48-
q.add("value4")
49-
if wantLen, gotLen := 3, len(q.queue); wantLen != gotLen {
50-
t.Errorf("got queue length %d want %d", gotLen, wantLen)
51-
}
52-
if wantDropCount, gotDropCount := 2, q.droppedCount; wantDropCount != gotDropCount {
53-
t.Errorf("got drop count %d want %d", gotDropCount, wantDropCount)
54-
}
55-
wantArr := []string{"value3", "value1", "value4"}
56-
gotArr := q.queueToArray()
58+
gotValues := make([]string, len(wantValues))
59+
for i := 0; i < len(gotValues); i++ {
60+
gotValues[i] = q.readNext().(string)
61+
}
5762

58-
if wantLen, gotLen := len(wantArr), len(gotArr); gotLen != wantLen {
59-
t.Errorf("got array len %d want %d", gotLen, wantLen)
60-
}
63+
if !reflect.DeepEqual(wantValues, gotValues) {
64+
t.Errorf("got array = %#v; want %#v", gotValues, wantValues)
65+
}
6166

62-
if !reflect.DeepEqual(gotArr, wantArr) {
63-
t.Errorf("got array = %#v; want %#v", gotArr, wantArr)
64-
}
67+
if wantDroppedCount != q.droppedCount {
68+
t.Errorf("got dropped count %d want %d", q.droppedCount, wantDroppedCount)
69+
}
70+
})
6571
}

trace/trace.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,15 @@ func (s *Span) makeSpanData() *SpanData {
300300
sd.Attributes = s.lruAttributesToAttributeMap()
301301
sd.DroppedAttributeCount = s.lruAttributes.droppedCount
302302
}
303-
if len(s.annotations.queue) > 0 {
303+
if len(s.annotations.ringQueue) > 0 {
304304
sd.Annotations = s.interfaceArrayToAnnotationArray()
305305
sd.DroppedAnnotationCount = s.annotations.droppedCount
306306
}
307-
if len(s.messageEvents.queue) > 0 {
307+
if len(s.messageEvents.ringQueue) > 0 {
308308
sd.MessageEvents = s.interfaceArrayToMessageEventArray()
309309
sd.DroppedMessageEventCount = s.messageEvents.droppedCount
310310
}
311-
if len(s.links.queue) > 0 {
311+
if len(s.links.ringQueue) > 0 {
312312
sd.Links = s.interfaceArrayToLinksArray()
313313
sd.DroppedLinkCount = s.links.droppedCount
314314
}
@@ -345,25 +345,25 @@ func (s *Span) SetStatus(status Status) {
345345
}
346346

347347
func (s *Span) interfaceArrayToLinksArray() []Link {
348-
linksArr := make([]Link, 0, len(s.links.queue))
349-
for _, value := range s.links.queue {
350-
linksArr = append(linksArr, value.(Link))
348+
linksArr := make([]Link, len(s.links.ringQueue))
349+
for i := 0; i < len(linksArr); i++ {
350+
linksArr[i] = s.links.readNext().(Link)
351351
}
352352
return linksArr
353353
}
354354

355355
func (s *Span) interfaceArrayToMessageEventArray() []MessageEvent {
356-
messageEventArr := make([]MessageEvent, 0, len(s.messageEvents.queue))
357-
for _, value := range s.messageEvents.queue {
358-
messageEventArr = append(messageEventArr, value.(MessageEvent))
356+
messageEventArr := make([]MessageEvent, len(s.messageEvents.ringQueue))
357+
for i := 0; i < len(messageEventArr); i++ {
358+
messageEventArr[i] = s.messageEvents.readNext().(MessageEvent)
359359
}
360360
return messageEventArr
361361
}
362362

363363
func (s *Span) interfaceArrayToAnnotationArray() []Annotation {
364-
annotationArr := make([]Annotation, 0, len(s.annotations.queue))
365-
for _, value := range s.annotations.queue {
366-
annotationArr = append(annotationArr, value.(Annotation))
364+
annotationArr := make([]Annotation, len(s.annotations.ringQueue))
365+
for i := 0; i < len(annotationArr); i++ {
366+
annotationArr[i] = s.annotations.readNext().(Annotation)
367367
}
368368
return annotationArr
369369
}

0 commit comments

Comments
 (0)