Sync.Pool
Suppose your Go program has many threads (called with the go
-keyword) and they each use a buffer to create a response. It is possible to reuse these buffers with sync.Pool
.
With sync.Pool
, part of the sync module, we specify a New method that allocates an object, and then can call Get()
and Put()
to access it on any thread. This reduces allocations on many threads.
This program runs 100 threads with the go
-keyword, and has a shared sync.Pool
that returns strings.Builder
instances. Each thread uses an instance of a Builder to generate data.
sync.Pool
—it is important to define a New()
function that returns an allocated object here.main()
we run 100 goroutines, and each goroutine runs the Test()
function.sync.Pool
, and now have access to an allocated strings.Builder
instance. We Put the builder back when we are done.time.Sleep
—this could be done with a WaitGroup
instead.package main import ( "fmt" "strconv" "strings" "sync" "time" ) // Part 1: create sync.Pool for reusing a strings.Builder on many goroutines. var builderPool = sync.Pool{ New: func() any { return new(strings.Builder) }, } func Test(i int) { // Part 3: Get the shared strings.Builder, and Put it back when we are done. b := builderPool.Get().(*strings.Builder) b.WriteString("Hey friends, ") b.WriteString("how are things? ") b.WriteString(strconv.Itoa(i)) fmt.Println(b.String()) b.Reset() builderPool.Put(b) } func main() { // Part 2: run 100 goroutines. for i := range 100 { go Test(i) } // Part 4: sleep for a minute to allow the threads to complete. time.Sleep(time.Duration(time.Minute)) }Hey friends, how are things? 1 Hey friends, how are things? 31 Hey friends, how are things? 11 ... Hey friends, how are things? 79 Hey friends, how are things? 80 Hey friends, how are things? 73
As with most performance optimizations, sync.Pool
can make programs faster or slower. For the case of buffers, like with strings.Builder
or bytes.Buffer
, it is probably helpful.
sync.Pool
may be slower than just doing an allocation.To reduce the work of the garbage collector in Go, we can employ the sync.Pool
type. This can reduce total allocations, but adds some threaded instructions to manage the pool correctly.