From 2f5c2aa6be307187467de1e98877eeffc729c74e Mon Sep 17 00:00:00 2001 From: Vladimir Mihailenco Date: Mon, 20 Aug 2012 12:00:59 +0300 Subject: [PATCH] parser: Optimize multi bulk request parsing. --- parser.go | 12 ++---------- request.go => req.go | 0 request_test.go => req_test.go | 34 +++++++++++++++++++++++----------- 3 files changed, 25 insertions(+), 21 deletions(-) rename request.go => req.go (100%) rename request_test.go => req_test.go (62%) diff --git a/parser.go b/parser.go index 15b46c1d..1073eb88 100644 --- a/parser.go +++ b/parser.go @@ -114,16 +114,12 @@ func _parseReply(rd reader, useIfaceSlice bool) (interface{}, error) { } if useIfaceSlice { - vals := make([]interface{}, 0) - if len(line) == 2 && line[1] == '0' { - return vals, nil - } - numReplies, err := strconv.ParseInt(string(line[1:]), 10, 64) if err != nil { return nil, err } + vals := make([]interface{}, 0, numReplies) for i := int64(0); i < numReplies; i++ { v, err := parseReply(rd) if err == Nil { @@ -137,16 +133,12 @@ func _parseReply(rd reader, useIfaceSlice bool) (interface{}, error) { return vals, nil } else { - vals := make([]string, 0) - if len(line) == 2 && line[1] == '0' { - return vals, nil - } - numReplies, err := strconv.ParseInt(string(line[1:]), 10, 64) if err != nil { return nil, err } + vals := make([]string, 0, numReplies) for i := int64(0); i < numReplies; i++ { v, err := parseReply(rd) if err != nil { diff --git a/request.go b/req.go similarity index 100% rename from request.go rename to req.go diff --git a/request_test.go b/req_test.go similarity index 62% rename from request_test.go rename to req_test.go index ff670c2e..18ba99f2 100644 --- a/request_test.go +++ b/req_test.go @@ -35,21 +35,17 @@ func (t *RequestTest) TearDownTest(c *C) {} //------------------------------------------------------------------------------ -func (t *RequestTest) BenchmarkStatusReq(c *C) { +func (t *RequestTest) benchmarkReq(c *C, reqString string, req redis.Req, checker Checker, expected interface{}) { c.StopTimer() - lineReader := NewLineReader([]byte("+OK\r\n")) + lineReader := NewLineReader([]byte(reqString)) rd := bufio.NewReaderSize(lineReader, 1024) - req := redis.NewStatusReq() for i := 0; i < 10; i++ { - vI, err := req.ParseReply(rd) + vIface, err := req.ParseReply(rd) c.Check(err, IsNil) - c.Check(vI, Equals, "OK") - - req.SetVal(vI) - c.Check(req.Err(), IsNil) - c.Check(req.Val(), Equals, "OK") + c.Check(vIface, checker, expected) + req.SetVal(vIface) } c.StartTimer() @@ -57,7 +53,23 @@ func (t *RequestTest) BenchmarkStatusReq(c *C) { for i := 0; i < c.N; i++ { v, _ := req.ParseReply(rd) req.SetVal(v) - req.Err() - req.Val() } } + +func (t *RequestTest) BenchmarkStatusReq(c *C) { + t.benchmarkReq(c, "+OK\r\n", redis.NewStatusReq(), Equals, "OK") +} + +func (t *RequestTest) BenchmarkStringReq(c *C) { + t.benchmarkReq(c, "$5\r\nhello\r\n", redis.NewStringReq(), Equals, "hello") +} + +func (t *RequestTest) BenchmarkStringSliceReq(c *C) { + t.benchmarkReq( + c, + "*2\r\n$5\r\nhello\r\n$5\r\nhello\r\n", + redis.NewStringSliceReq(), + DeepEquals, + []string{"hello", "hello"}, + ) +}