Use a sync.pool for the staging buffer in codec.go.

Change-Id: I1aae6847f77b5a7c75582b07c199b1943cf90552
This commit is contained in:
Bjoern Rabenstein 2014-09-09 17:16:59 +02:00
parent 4770cf76a4
commit e7cb9ddb9f
1 changed files with 29 additions and 25 deletions

View File

@ -17,24 +17,30 @@ type codable interface {
encoding.BinaryUnmarshaler encoding.BinaryUnmarshaler
} }
// TODO: yeah, this ain't ideal. A lot of locking and possibly even contention. var bufPool sync.Pool
var tmpBufMtx sync.Mutex
var tmpBuf = make([]byte, binary.MaxVarintLen64)
func setTmpBufLen(l int) { func getBuf(l int) []byte {
if cap(tmpBuf) >= l { x := bufPool.Get()
tmpBuf = tmpBuf[:l] if x == nil {
} else { return make([]byte, l)
tmpBuf = make([]byte, l)
} }
buf := x.([]byte)
if cap(buf) < l {
return make([]byte, l)
}
return buf[:l]
}
func putBuf(buf []byte) {
bufPool.Put(buf)
} }
func encodeVarint(b *bytes.Buffer, i int) error { func encodeVarint(b *bytes.Buffer, i int) error {
tmpBufMtx.Lock() buf := getBuf(binary.MaxVarintLen64)
defer tmpBufMtx.Unlock() defer putBuf(buf)
bytesWritten := binary.PutVarint(tmpBuf, int64(i)) bytesWritten := binary.PutVarint(buf, int64(i))
if _, err := b.Write(tmpBuf[:bytesWritten]); err != nil { if _, err := b.Write(buf[:bytesWritten]); err != nil {
return err return err
} }
return nil return nil
@ -54,14 +60,13 @@ func decodeString(b *bytes.Reader) (string, error) {
return "", err return "", err
} }
tmpBufMtx.Lock() buf := getBuf(int(length))
defer tmpBufMtx.Unlock() defer putBuf(buf)
setTmpBufLen(int(length)) if _, err := io.ReadFull(b, buf); err != nil {
if _, err := io.ReadFull(b, tmpBuf); err != nil {
return "", err return "", err
} }
return string(tmpBuf), nil return string(buf), nil
} }
type codableMetric clientmodel.Metric type codableMetric clientmodel.Metric
@ -112,20 +117,19 @@ func (fp *codableFingerprint) UnmarshalBinary(buf []byte) error {
type codableFingerprints clientmodel.Fingerprints type codableFingerprints clientmodel.Fingerprints
func (fps codableFingerprints) MarshalBinary() ([]byte, error) { func (fps codableFingerprints) MarshalBinary() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0, binary.MaxVarintLen64+len(fps)*8)) b := bytes.NewBuffer(make([]byte, 0, binary.MaxVarintLen64+len(fps)*8))
encodeVarint(buf, len(fps)) encodeVarint(b, len(fps))
tmpBufMtx.Lock() buf := getBuf(8)
defer tmpBufMtx.Unlock() defer putBuf(buf)
setTmpBufLen(8)
for _, fp := range fps { for _, fp := range fps {
binary.BigEndian.PutUint64(tmpBuf, uint64(fp)) binary.BigEndian.PutUint64(buf, uint64(fp))
if _, err := buf.Write(tmpBuf[:8]); err != nil { if _, err := b.Write(buf[:8]); err != nil {
return nil, err return nil, err
} }
} }
return buf.Bytes(), nil return b.Bytes(), nil
} }
func (fps *codableFingerprints) UnmarshalBinary(buf []byte) error { func (fps *codableFingerprints) UnmarshalBinary(buf []byte) error {