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 Aug 9, 2022
1 parent a209843 commit e580b4e
Showing 1 changed file with 13 additions and 2 deletions.
15 changes: 13 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,27 @@ 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.
return (*[maxArraySize]byte)(v.(unsafe.Pointer))[:0:size]
}
}
}
Expand Down

0 comments on commit e580b4e

Please sign in to comment.