Skip to content

Instantly share code, notes, and snippets.

@ifraixedes
Created October 15, 2025 17:35
Show Gist options
  • Save ifraixedes/912c6260ac5de02c649c05140b27f9bb to your computer and use it in GitHub Desktop.
Save ifraixedes/912c6260ac5de02c649c05140b27f9bb to your computer and use it in GitHub Desktop.
The Go test file that used to benchmark allocations of sync.Pool and I wrote a post about https://blog.fraixed.es/post/move-to-heap-golang-std-pool
// This was a benchmark that I used to understand how to use sync.Pool without allocations.
// Pointers key as stated in the documentation, but how you use them is also important.
// I wrote about it in https://blog.fraixed.es/post/move-to-heap-golang-std-pool
// To execute the benchmarks use `go test -bench . -benchmem`. The only interesting part is the last
// column, the `allocs/op`; when the benchmark function shows 0 is good, otherwise is bad.
package tmp
import (
"sync"
"testing"
)
const numElems = 10000
func BenchmarkPoolPointer(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
s := pool.Get().(*[]byte)
if len(*s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s2 := *s
s2 = s2[:0]
pool.Put(&s2)
for b.Loop() {
s := pool.Get().(*[]byte)
s2 := *s
s2 = append(s2, 10)
if len(s2) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s2 = s2[:0]
pool.Put(&s2)
}
}
func BenchmarkPoolPointer2(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
s := pool.Get().(*[]byte)
if len(*s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s2 := *s
s2 = s2[:0]
*s = s2
pool.Put(s)
for b.Loop() {
s := pool.Get().(*[]byte)
s2 := *s
s2 = append(s2, 10)
if len(s2) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s2 = s2[:0]
*s = s2
pool.Put(s)
}
}
func BenchmarkPoolPointer3(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
s := pool.Get().(*[]byte)
if len(*s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
*s = (*s)[:0]
pool.Put(s)
for b.Loop() {
s := pool.Get().(*[]byte)
*s = append(*s, 10)
if len(*s) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
*s = (*s)[:0]
pool.Put(s)
}
}
func BenchmarkPoolValue(b *testing.B) {
pool := sync.Pool{
New: func() any {
return make([]byte, 0, numElems)
},
}
s := pool.Get().([]byte)
if len(s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = s[:0]
pool.Put(s)
for b.Loop() {
s := pool.Get().([]byte)
s = append(s, 10)
if len(s) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = s[:0]
pool.Put(s)
}
}
func BenchmarkPoolWrapper(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
get := func() []byte {
s := pool.Get().(*[]byte)
return *s
}
put := func(s []byte) {
pool.Put(&s)
}
s := get()
if len(s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = s[:0]
put(s)
for b.Loop() {
s := get()
s = append(s, 10)
if len(s) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = s[:0]
put(s)
}
}
func BenchmarkPoolWrapperPointers(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
appendByte := func(buffer *[]byte, val byte) *[]byte {
b := *buffer
b = append(b, val)
return &b
}
reset := func(buffer *[]byte) *[]byte {
b := *buffer
b = b[:0]
return &b
}
s := pool.Get().(*[]byte)
if len(*s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = reset(s)
pool.Put(s)
for b.Loop() {
s := pool.Get().(*[]byte)
s = appendByte(s, 10)
if len(*s) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = reset(s)
pool.Put(s)
}
}
func BenchmarkPoolWrapperPointers2(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
appendByte := func(buffer *[]byte, val byte) *[]byte {
b := *buffer
b = append(b, val)
*buffer = b
return buffer
}
reset := func(buffer *[]byte) *[]byte {
b := *buffer
b = b[:0]
*buffer = b
return buffer
}
s := pool.Get().(*[]byte)
if len(*s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = reset(s)
pool.Put(s)
for b.Loop() {
s := pool.Get().(*[]byte)
s = appendByte(s, 10)
if len(*s) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = reset(s)
pool.Put(s)
}
}
func BenchmarkPoolWrapperPointers3(b *testing.B) {
pool := sync.Pool{
New: func() any {
s := make([]byte, 0, numElems)
return &s
},
}
appendByte := func(buffer *[]byte, val byte) *[]byte {
b := append(*buffer, val)
*buffer = b
return buffer
}
reset := func(buffer *[]byte) *[]byte {
b := *buffer
b = b[:0]
*buffer = b
return buffer
}
s := pool.Get().(*[]byte)
if len(*s) != 0 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = reset(s)
pool.Put(s)
for b.Loop() {
s := pool.Get().(*[]byte)
s = appendByte(s, 10)
if len(*s) != 1 {
b.Error("returned slice doesn't have the expected number of elements")
}
s = reset(s)
pool.Put(s)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment