diff --git a/benchmarks/decode_test.go b/benchmarks/decode_test.go index aad5683..97c9a56 100644 --- a/benchmarks/decode_test.go +++ b/benchmarks/decode_test.go @@ -1,6 +1,7 @@ package benchmark import ( + "bytes" "encoding/json" "testing" @@ -49,6 +50,17 @@ func Benchmark_Decode_SmallStruct_GoJayUnsafe(b *testing.B) { } } +func Benchmark_Decode_SmallStruct_GoJsonDecode(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + result := SmallPayload{} + buf := bytes.NewBuffer(SmallFixture) + if err := gojson.NewDecoder(buf).Decode(&result); err != nil { + b.Fatal(err) + } + } +} + func Benchmark_Decode_SmallStruct_GoJson(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/decode.go b/decode.go index 6975ad5..2d9ff8e 100644 --- a/decode.go +++ b/decode.go @@ -2,7 +2,6 @@ package json import ( "encoding" - "fmt" "io" "reflect" "strconv" diff --git a/decode_int.go b/decode_int.go index 5e9a3d6..0c445f8 100644 --- a/decode_int.go +++ b/decode_int.go @@ -64,6 +64,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) { break } num := s.buf[start:s.cursor] + s.reset() if len(num) < 2 { return nil, errInvalidCharacter(s.char(), "number(integer)", s.totalOffset()) } @@ -77,6 +78,7 @@ func (d *intDecoder) decodeStreamByte(s *stream) ([]byte, error) { break } num := s.buf[start:s.cursor] + s.reset() return num, nil default: return nil, errInvalidCharacter(s.char(), "number(integer)", s.totalOffset()) diff --git a/decode_stream.go b/decode_stream.go index 817e612..522bfa7 100644 --- a/decode_stream.go +++ b/decode_stream.go @@ -63,20 +63,29 @@ func (s *stream) reset() { } func (s *stream) read() bool { + if s.allRead { + return false + } buf := make([]byte, readChunkSize) n, err := s.r.Read(buf) if err != nil && err != io.EOF { return false } - remain := s.length - newBuf := make([]byte, remain+int64(n)+1) - copy(newBuf, s.buf) - copy(newBuf[remain:], buf) - s.buf = newBuf - s.length = int64(len(newBuf)) - 1 - s.offset += s.cursor - if n == 0 || err == io.EOF { + if n < readChunkSize || err == io.EOF { s.allRead = true + } + totalSize := s.length + int64(n) + 1 + if totalSize > readChunkSize { + newBuf := make([]byte, totalSize) + copy(newBuf, s.buf) + copy(newBuf[s.length:], buf) + s.buf = newBuf + } else { + s.buf = buf + } + s.length = int64(len(s.buf)) - 1 + s.offset += s.cursor + if n == 0 { return false } return true