Skip to content

Commit ec47126

Browse files
author
Frediano Ziglio
committed
Avoid extra allocation using buffer pools
Inserting directly a slice into a sync.Pool object caused the allocation for an extra object every Put call. Avoid it using unsafe.Pointer to the underlying array. Signed-off-by: Frediano Ziglio <[email protected]>
1 parent a209843 commit ec47126

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

buffer/pool.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io"
77
"net"
88
"sync"
9+
"unsafe"
910
)
1011

1112
// PoolConfig contains configuration for the allocation and reuse strategy.
@@ -47,17 +48,28 @@ func putBuf(buf []byte) {
4748
return
4849
}
4950
if c := buffers[size]; c != nil {
50-
c.Put(buf[:0])
51+
// Save un unsafe pointer to the array instead of the slice to
52+
// avoid an extra allocation.
53+
// We don't care about the length and we know the capability so
54+
// we don't need to save anything else.
55+
c.Put(unsafe.Pointer(&buf[:1][0]))
5156
}
5257
}
5358

59+
const maxArraySize = uint((uint64(1) << 50 - 1) & uint64(^uint(0) >> 1))
60+
5461
// getBuf gets a chunk from reuse pool or creates a new one if reuse failed.
5562
func getBuf(size int) []byte {
5663
if size >= config.PooledSize {
5764
if c := buffers[size]; c != nil {
5865
v := c.Get()
5966
if v != nil {
60-
return v.([]byte)
67+
// Recreate back the original slice.
68+
// Get back the array and add length and capability.
69+
// Limiting the array to the proper capability will make this
70+
// safe.
71+
buf := (*[maxArraySize]byte)(v.(unsafe.Pointer))
72+
return buf[:0:size]
6173
}
6274
}
6375
}

0 commit comments

Comments
 (0)