Unified pooling for redis client in hspatial requests.

This commit is contained in:
Sascha L. Teichmann 2017-02-28 18:50:45 +01:00
parent 3ba10aa00a
commit 7fca02e45f
2 changed files with 22 additions and 40 deletions

View File

@ -81,6 +81,10 @@ func DecodeStringFromBytes(key []byte) (pos int64, err error) {
return strconv.ParseInt(string(key), 10, 64) 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 { func StringToBytes(key int64) []byte {
return strconv.AppendInt(nil, key, 10) return strconv.AppendInt(nil, key, 10)
} }

View File

@ -41,47 +41,21 @@ var (
ignore = []byte("IGNORE") ignore = []byte("IGNORE")
) )
// stringPool is a pool to help recycle bulk strings var bufPool = sync.Pool{
// for writing. Experimented with sync.Pool and New: func() interface{} {
// channel based leaky buffers but the mutex based // Some fun with slices
// version performs best in this case. buf := make([]byte, 40)
type stringPool struct { return [2][]byte{buf[:20:20][:0], buf[20:][:0]}
list [][]byte },
sync.Mutex
} }
func (sp *stringPool) alloc() (l []byte) { func (client *RedisClient) writeBulkString(buf []byte, data []byte) (err error) {
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()
buf = append(buf, '$') buf = append(buf, '$')
buf = strconv.AppendInt(buf, int64(len(data)), 10) buf = strconv.AppendInt(buf, int64(len(data)), 10)
buf = append(buf, nl...) buf = append(buf, nl...)
buf = append(buf, data...) buf = append(buf, data...)
buf = append(buf, nl...) buf = append(buf, nl...)
_, err = client.conn.Write(buf) _, err = client.conn.Write(buf)
spool.free(buf)
return return
} }
@ -89,16 +63,20 @@ func (client *RedisClient) writeHSpatial(p1, p2 int64) (err error) {
if _, err = client.conn.Write(writeArray4); err != nil { if _, err = client.conn.Write(writeArray4); err != nil {
return return
} }
if err = client.writeBulkString(hspatial); err != nil { buf := bufPool.Get().([2][]byte)
return // 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 { if err = client.writeBulkString(buf[0], ignore); err != nil {
return goto exit
} }
if err = client.writeBulkString(StringToBytes(p1)); err != nil { if err = client.writeBulkString(buf[0], keyToBytes(p1, buf[1])); err != nil {
return goto exit
} }
err = client.writeBulkString(StringToBytes(p2)) err = client.writeBulkString(buf[0], keyToBytes(p2, buf[1]))
exit:
bufPool.Put(buf)
return return
} }