Improves performance

This commit is contained in:
Eelco Cramer 2020-10-09 15:06:47 +02:00
parent 97bbed8a92
commit 39571ccc56
No known key found for this signature in database
GPG Key ID: 92BE398A20135E17
2 changed files with 30 additions and 16 deletions

View File

@ -55,13 +55,10 @@ func (r *Reader) Reset(rd io.Reader) {
} }
func (r *Reader) ReadLine() ([]byte, error) { func (r *Reader) ReadLine() ([]byte, error) {
line, err := r.rd.ReadBytes('\n') line, err := r.readLine()
if err != nil && err != io.EOF { if err != nil {
return nil, err return nil, err
} }
if len(line) == 0 {
return nil, fmt.Errorf("redis: reply is empty")
}
if isNilReply(line) { if isNilReply(line) {
return nil, Nil return nil, Nil
} }
@ -72,15 +69,29 @@ func (r *Reader) ReadLine() ([]byte, error) {
// - there is a pending read error; // - there is a pending read error;
// - or line does not end with \r\n. // - or line does not end with \r\n.
func (r *Reader) readLine() ([]byte, error) { func (r *Reader) readLine() ([]byte, error) {
var s []byte
multi := false
for {
b, err := r.rd.ReadSlice('\n') b, err := r.rd.ReadSlice('\n')
if err != nil { if err != nil {
// in case the end of the buffer is not reached
if err == bufio.ErrBufferFull {
s = append(s, b...)
multi = true
continue
} else {
return nil, err return nil, err
} }
}
if len(b) <= 2 || b[len(b)-1] != '\n' || b[len(b)-2] != '\r' { if len(b) <= 2 || b[len(b)-1] != '\n' || b[len(b)-2] != '\r' {
return nil, fmt.Errorf("redis: invalid reply: %q", b) return nil, fmt.Errorf("redis: invalid reply: %q", b)
} }
if multi {
b = append(s, b...)
}
b = b[:len(b)-2] b = b[:len(b)-2]
return b, nil return b, nil
}
} }
func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) { func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) {

View File

@ -2,6 +2,7 @@ package proto_test
import ( import (
"bytes" "bytes"
"io"
"testing" "testing"
"github.com/go-redis/redis/v8/internal/proto" "github.com/go-redis/redis/v8/internal/proto"
@ -29,14 +30,16 @@ func BenchmarkReader_ParseReply_Slice(b *testing.B) {
func TestReader_ReadLine(t *testing.T) { func TestReader_ReadLine(t *testing.T) {
original := bytes.Repeat([]byte("a"), 8192) original := bytes.Repeat([]byte("a"), 8192)
original[len(original)-2] = '\r'
original[len(original)-1] = '\n'
r := proto.NewReader(bytes.NewReader(original)) r := proto.NewReader(bytes.NewReader(original))
read, err := r.ReadLine() read, err := r.ReadLine()
if err != nil { if err != nil && err != io.EOF {
t.Errorf("Should be able to read the full buffer: %v", err) t.Errorf("Should be able to read the full buffer: %v", err)
} }
if bytes.Compare(read, original) != 0 { if bytes.Compare(read, original[:len(original)-2]) != 0 {
t.Errorf("Values must be equal: %q", read) t.Errorf("Values must be equal: %d expected %d", len(read), len(original[:len(original)-2]))
} }
} }