From 7fca02e45f38b946be5d9a41594043ca67a06090 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Tue, 28 Feb 2017 18:50:45 +0100 Subject: [PATCH] Unified pooling for redis client in hspatial requests. --- common/coords.go | 4 +++ common/redisclient.go | 58 ++++++++++++++----------------------------- 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/common/coords.go b/common/coords.go index f66c365..03ec866 100644 --- a/common/coords.go +++ b/common/coords.go @@ -81,6 +81,10 @@ func DecodeStringFromBytes(key []byte) (pos int64, err error) { return strconv.ParseInt(string(key), 10, 64) } +func keyToBytes(key int64, buf []byte) []byte { + return strconv.AppendInt(buf, key, 10) +} + func StringToBytes(key int64) []byte { return strconv.AppendInt(nil, key, 10) } diff --git a/common/redisclient.go b/common/redisclient.go index 3149259..cc90b71 100644 --- a/common/redisclient.go +++ b/common/redisclient.go @@ -41,47 +41,21 @@ var ( ignore = []byte("IGNORE") ) -// stringPool is a pool to help recycle bulk strings -// for writing. Experimented with sync.Pool and -// channel based leaky buffers but the mutex based -// version performs best in this case. -type stringPool struct { - list [][]byte - sync.Mutex +var bufPool = sync.Pool{ + New: func() interface{} { + // Some fun with slices + buf := make([]byte, 40) + return [2][]byte{buf[:20:20][:0], buf[20:][:0]} + }, } -func (sp *stringPool) alloc() (l []byte) { - sp.Lock() - if n := len(sp.list); n > 0 { - l = sp.list[n-1] - sp.list[n-1] = nil - sp.list = sp.list[:n-1] - sp.Unlock() - } else { - sp.Unlock() - l = make([]byte, 0, 32) - } - return -} - -func (sp *stringPool) free(b []byte) { - b = b[:0] - sp.Lock() - sp.list = append(sp.list, b) - sp.Unlock() -} - -var spool stringPool - -func (client *RedisClient) writeBulkString(data []byte) (err error) { - buf := spool.alloc() +func (client *RedisClient) writeBulkString(buf []byte, data []byte) (err error) { buf = append(buf, '$') buf = strconv.AppendInt(buf, int64(len(data)), 10) buf = append(buf, nl...) buf = append(buf, data...) buf = append(buf, nl...) _, err = client.conn.Write(buf) - spool.free(buf) return } @@ -89,16 +63,20 @@ func (client *RedisClient) writeHSpatial(p1, p2 int64) (err error) { if _, err = client.conn.Write(writeArray4); err != nil { return } - if err = client.writeBulkString(hspatial); err != nil { - return + buf := bufPool.Get().([2][]byte) + // defer bufPool.Put(buf) // not used to avoid allocation. + if err = client.writeBulkString(buf[0], hspatial); err != nil { + goto exit } - if err = client.writeBulkString(ignore); err != nil { - return + if err = client.writeBulkString(buf[0], ignore); err != nil { + goto exit } - if err = client.writeBulkString(StringToBytes(p1)); err != nil { - return + if err = client.writeBulkString(buf[0], keyToBytes(p1, buf[1])); err != nil { + goto exit } - err = client.writeBulkString(StringToBytes(p2)) + err = client.writeBulkString(buf[0], keyToBytes(p2, buf[1])) +exit: + bufPool.Put(buf) return }