Skip to content

Commit

Permalink
Add ability to reuse Decoder,Scanner, and byteReader
Browse files Browse the repository at this point in the history
  • Loading branch information
pboyd04 committed Feb 21, 2025
1 parent 703c45d commit fbae326
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 0 deletions.
13 changes: 13 additions & 0 deletions bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ func BenchmarkDecoderDecodeInterfaceAny(b *testing.B) {
check(b, err)
}
})
b.Run("pkgjson/reuse/"+tc.path, func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(r.Size())
b.ResetTimer()
dec := NewDecoderBuffer(r, buf[:])
for i := 0; i < b.N; i++ {
r.Seek(0, 0)
dec.Reset(r)
var i interface{}
err := dec.Decode(&i)
check(b, err)
}
})
b.Run("encodingjson/"+tc.path, func(b *testing.B) {
b.ReportAllocs()
b.SetBytes(r.Size())
Expand Down
7 changes: 7 additions & 0 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ func (d *Decoder) NextToken() ([]byte, error) {
return d.state(d)
}

// Reset resets the decoder to read from a new io.Reader to avoid reallocation.
func (d *Decoder) Reset(r io.Reader) {
d.scanner.Reset(r)
d.state = (*Decoder).stateValue
d.stack = d.stack[:0]
}

func (d *Decoder) stateObjectString() ([]byte, error) {
tok := d.scanner.Next()
if len(tok) < 1 {
Expand Down
8 changes: 8 additions & 0 deletions reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ func (b *byteReader) compact() {
copy(b.data, b.data[b.offset:])
b.offset = 0
}

// reset resets the byteReader to read from a new r without reallocating.
func (b *byteReader) reset(r io.Reader) {
b.data = b.data[:0]
b.offset = 0
b.r = r
b.err = nil
}
6 changes: 6 additions & 0 deletions scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ func (s *Scanner) Next() []byte {
}
}

// Reset resets the scanner to read from a new io.Reader to avoid reallocation.
func (s *Scanner) Reset(r io.Reader) {
s.br.reset(r)
s.offset = 0
}

func (s *Scanner) validateToken(expected string) int {
for {
w := s.br.window()
Expand Down

0 comments on commit fbae326

Please sign in to comment.