Why you should like sync.Pool?
Because it’s fast . x4982 reducing memory usage and repository with benchmarks below.
Ok. What the hell?
The garbage collector runs at regular intervals. In case your code constantly allocates memory in some data structures and then frees them, this requires constant work of the collector, more memory and cpu usage for allocating resources on init structs.
The comments on sync/pool.go say that:A Pool is a set of temporary objects that may be individually saved and retrieved.A Pool is safe for use by multiple goroutines simultaneously.
sync.Pool allows us to reuse memory without allocate.
Also if you are have http server which wait post requests with json body and it must decode to the structure you can use sync.Pool to save memory and reduce server response time.
sync.Pool usage
sync.Pool construction is simple:
var bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
Now you have pool which will be create and new buffers. You can get you first buffer here:
buffer := bufferPool.Get().(*bytes.Buffer)
Method get will return already existing *bytes.Buffer in the pool and if it’s not will call method New which init new *bytes.Buffer
But after buffer usage you must reset and put it to pool back:
buffer.Reset()
bufferPool.Put(buffer)
Benchmarking
Encoding json to the bytes.Buffer
// That code tried to json encode structureBenchmarkReadStreamWithPool-8 5000000 384 ns/op 0 B/op 0 allocs/op
BenchmarkReadStreamWithoutPool-8 3000000 554 ns/op 160 B/op 2 allocs/op
We have 44% performance boost and save very-very much memory (160B/ops vs 0B/ops)
Writing bytes to bufio.Writer
BenchmarkWriteBufioWithPool-8 10000000 123 ns/op 128 B/op 2 allocs/op
BenchmarkWriteBufioWithoutPool-8 2000000 651 ns/op 4288 B/op 4 allocs/op
We have x5 performance boost and x32 reduced memory usage
Decoding json to struct
BenchmarkJsonDecodeWithPool-8 1000000 1729 ns/op 1128 B/op 8 allocs/op
BenchmarkJsonDecodeWithoutPool-8 1000000 1751 ns/op 1160 B/op 9 allocs/op
We have 1% performance boost because json decode is too hard operation and we cannot see normal boost by the reusing structures.
Gzip bytes
BenchmarkWriteGzipWithPool-8 500000 2339 ns/op 162 B/op 2 allocs/op
BenchmarkWriteGzipWithoutPool-8 10000 105288 ns/op 807088 B/op 16 allocs/op
Stop, what? x45 performance boost and x4982 reduced memory usage
Conclusion
Always use sync.Pool when you can! It really saves memory and increase performance of you application.
Github repository with benchmarks here.
📝 Read this story later in Journal.
👩💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.