forked from mirror/redis
Improves performance
This commit is contained in:
parent
97bbed8a92
commit
39571ccc56
|
@ -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,16 +69,30 @@ 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) {
|
||||||
line, err := r.ReadLine()
|
line, err := r.ReadLine()
|
||||||
|
|
|
@ -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]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue