Skip to content

Commit

Permalink
Avoid extra allocation using buffer pools
Browse files Browse the repository at this point in the history
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 <fziglio@cyral.com>
  • Loading branch information
Frediano Ziglio committed Apr 27, 2022
1 parent a209843 commit ec47126
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions buffer/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"net"
"sync"
"unsafe"
)

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

const maxArraySize = uint((uint64(1) << 50 - 1) & uint64(^uint(0) >> 1))

// getBuf gets a chunk from reuse pool or creates a new one if reuse failed.
func getBuf(size int) []byte {
if size >= config.PooledSize {
if c := buffers[size]; c != nil {
v := c.Get()
if v != nil {
return v.([]byte)
// Recreate back the original slice.
// Get back the array and add length and capability.
// Limiting the array to the proper capability will make this
// safe.
buf := (*[maxArraySize]byte)(v.(unsafe.Pointer))
return buf[:0:size]
}
}
}
Expand Down

0 comments on commit ec47126

Please sign in to comment.