Skip to content

Commit

Permalink
fix(thrift): reduce skip decoder mem alloc/copy
Browse files Browse the repository at this point in the history
normally the ReaderSkipDecoder will be reused,
and it's hard to find out the issue with Benchmark.

In production, GC may happen all the time which make it eaiser to expose
the issue of calling `growSlow`
  • Loading branch information
xiaost committed Feb 6, 2025
1 parent 52ba607 commit a26dff7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 8 deletions.
13 changes: 9 additions & 4 deletions protocol/thrift/skipdecoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,15 @@ func (p *ReaderSkipDecoder) Grow(n int) {
}

func (p *ReaderSkipDecoder) growSlow(n int) {
// mcache will take care of the size of newb
newb := mcache.Malloc(p.n + n)
copy(newb, p.b[:p.n])
mcache.Free(p.b)
// mcache will take care of the new cap of newb to be power of 2
newb := mcache.Malloc((len(p.b) + n) | 255) // at least 255 bytes
newb = newb[:cap(newb)]
if p.n > 0 {
copy(newb, p.b[:p.n])
}
if p.b != nil {
mcache.Free(p.b)
}
p.b = newb
}

Expand Down
50 changes: 46 additions & 4 deletions protocol/thrift/skipdecoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,57 @@ func BenchmarkSkipDecoder(b *testing.B) {
}
sr.Release()

b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
sr := &BytesSkipDecoder{}
for pb.Next() {
b.Run("BytesSkipDecoder", func(b *testing.B) {
sr := NewBytesSkipDecoder(bs)
for i := 0; i < b.N; i++ {
_, err := sr.Next(STRUCT)
if err != nil {
b.Fatal(err)
}
sr.Reset(bs)
}
sr.Release()
})

b.Run("Parallel_BytesSkipDecoder", func(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
sr := NewBytesSkipDecoder(bs)
_, err := sr.Next(STRUCT)
if err != nil {
b.Fatal(err)
}
sr.Release()
}
})
})

b.Run("ReaderSkipDecoder", func(b *testing.B) {
r := bytes.NewReader(bs)
sr := NewReaderSkipDecoder(r)
for i := 0; i < b.N; i++ {
_, err := sr.Next(STRUCT)
if err != nil {
b.Fatal(err)
}
r.Reset(bs)
}
sr.Release()
})

b.Run("Parallel_ReaderSkipDecoder", func(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
r := bytes.NewReader(bs)
for pb.Next() {
sr := NewReaderSkipDecoder(r)
_, err := sr.Next(STRUCT)
if err != nil {
b.Fatal(err)
}
sr.Release()
r.Reset(bs)
}
})
})

}

0 comments on commit a26dff7

Please sign in to comment.