Scene
go If objects are frequently created and destroyed (such as json objects, log content, etc. of http service), it will put pressure on GC. For example, the followingLog
Functions, in high concurrency cases, require frequent creation and destruction of buffers.
func Log(w , key, val string) { b := new() // Print logs in a certain format, this paragraph is not the focus (().UTC().Format(time.RFC3339)) (' ') (key) ('=') (val) ('\n') (()) }
You can consider reusing these buffers at this time. We can maintain a buffer object pool, and when needed, take the buffer from the object pool and put it back into the object pool after use. It is recommended to use this time.
Maintain a group of object pools. When necessary, take objects from the object pool and do not need to be put back to the object pool. It has these characteristics:
- The object pool will be automatically expanded when busy, and the capacity will be automatically reduced when idle;
- Thread safety;
- Objects in the object pool will be automatically deleted without notice;
- Can't be copied.
usage
create
Specifies the New method during initialization. An object that will be created through the New method. Generally returns a pointer.
// When taking buffers from the object pool, if there is no buffer in the pool, call New to create a new one.var bufPool = { New: func() interface{} { return new() }, }
GET & PUT
Get the object of the object pool through Get. When used, return the object to the object pool through Put.
b := ().(*) // Take buffer object from object pool // Operation object, this is not important () (().UTC().Format(time.RFC3339)) // Put it back to the object pool after operation (b)
Optimize Log Functions
The log function can use optimization, the code is as follows:
var bufPool = { New: func() interface{} { return new() }, } func LogWithPool(w , key, val string) { // Take the buffer from the object pool b := ().(*) () // Print logs in a certain format, this paragraph is not the focus (().UTC().Format(time.RFC3339)) (' ') (key) ('=') (val) ('\n') (()) // Put back to the object pool (b) }
Performance Testing
We perform performance tests on two functions
// Not usedfunc BenchmarkLog(b *) { writer := (0, ) for n := 0; n < ; n++ { Log(writer, "path", "/search?a=flowers") } } // Use Reusefunc BenchmarkLogWithPool(b *) { writer := (0, ) for n := 0; n < ; n++ { LogWithPool(writer, "path", "/search?a=flowers") } }
result:
> go test -bench . -benchmem
goos: darwin
goarch: amd64
pkg: example/pool
cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
BenchmarkLog-8 1849365 635.0 ns/op 112 B/op 2 allocs/op
BenchmarkLogWithPool-8 1993304 614.4 ns/op 48 B/op 1 allocs/op
PASS
ok example/pool 4.333s
In contrast, when using and not using, the memory usage ratio is 48:112, and the optimization effect is quite obvious.
refer to:
[1]. /sync#Pool
The above is a detailed explanation of the usage example of Go programming library. For more information about Go library, please pay attention to my other related articles!