From 7f78feb9bd2d0bdeae55a37b478f68478d7bea30 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Sat, 25 Feb 2017 19:29:27 +0100 Subject: [PATCH] Replaced expensive fmt.Sscanf call in redis client with strconv.ParseInt. --- common/redisclient.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/common/redisclient.go b/common/redisclient.go index 2758ff8..d792cc1 100644 --- a/common/redisclient.go +++ b/common/redisclient.go @@ -6,10 +6,13 @@ package common import ( "bufio" + "bytes" + "errors" "fmt" "net" "strconv" "sync" + "unicode" ) type RedisClient struct { @@ -106,6 +109,16 @@ func isError(line []byte) error { return nil } +// parseSize is a cheaper replacement for fmt.Sscanf(string(line), "$%d\r\n", &size). +func parseSize(line []byte) (int, error) { + if len(line) < 1 || line[0] != '$' { + return 0, errors.New("Missing '$' at begin of line") + } + line = bytes.TrimFunc(line[1:], unicode.IsSpace) + v, err := strconv.ParseInt(string(line), 10, 0) + return int(v), err +} + func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) { var line []byte if line, err = client.reader.ReadBytes('\n'); err != nil { @@ -114,10 +127,7 @@ func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) { if err = isError(line); err != nil { return } - if _, err = fmt.Sscanf(string(line), "$%d\r\n", &size); err != nil { - return - } - if size <= 0 { + if size, err = parseSize(line); err != nil || size <= 0 { return } if cap(*data) < size { @@ -158,7 +168,7 @@ func (client *RedisClient) QueryCuboid(cuboid Cuboid, fn func(*Block)) (err erro return } block.Coord = PlainToCoord(key) - if size, err = client.readBulkString(&data); err != nil { + if size, err = client.readBulkString(&data); err != nil || size < 0 { return } block.Data = data[0:size]