Sync. Pool Usage scenario
Save and reuse temporary objects, reducing memory allocation and GC stress
example
type Student struct {
Name string
Age int32
Remark [1024]byte
}
var buf, _ = json.Marshal(Student{Name: "Geektutu", Age: 25})
func unmarsh() {
stu := &Student{}
json.Unmarshal(buf, stu)
}
Copy the code
Json deserialization is very common in the process of text parsing and network communication. When the program concurrency is very high, a large number of temporary variables need to be created in a short time, and these objects are allocated on the heap, which will cause great pressure to GC and seriously affect the performance of the program.
Sync. Pool is scalable and concurrency safe and is limited by memory size. Sync. Pool is used to store values that are allocated but not used, but may be used in the future. In this way, you do not need to allocate memory again and improve efficiency.
Sync. Pool is scalable and dynamically expanded when the load is high. Objects stored in the Pool are automatically cleared when they become inactive.
How to use
Declare an object pool
As long as the New function is implemented, there are no objects in the object pool, then the New function is called to create
var studentPool = sync.Pool{
New: func() interface{} {
return new(Student)
},
}
Copy the code
Get& Put
stu := studentPool.Get().(*Student)
json.Unmarshal(buf, stu)
studentPool.Put(stu)
Copy the code
- Get() is used to Get an object from the object pool because interface{} therefore requires a value type conversion when returning a value
- Put() will pool objects after they are used up
Struct performance test
package sync import ( "encoding/json" "sync" "testing" ) type Student struct { Name string Age int32 Remark [1024]byte } var studentPool = sync.Pool{New: func() interface{} { return new(Student) }} var buf, _ = json.Marshal(Student{Name: "Geektutu", Age: 25}) func BenchmarkUnmarshal(b *testing.B) { for n := 0; n < b.N; n++ { stu := &Student{} json.Unmarshal(buf, stu) } } func BenchmarkUnmarshalWithPool(b *testing.B) { for n := 0; n < b.N; n++ { stu := studentPool.Get().(*Student) json.Unmarshal(buf, stu) studentPool.Put(stu) } }Copy the code
Execute the command
go test -bench . -benchmem
Copy the code
The execution result is as follows:
goos: darwin goarch: amd64 pkg: code.byted.org/wangmingming.hit/GoProject/main/gobase/sync cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60ghz BenchmarkUnmarshal-12 13280 94006 NS/OP 1384 B/ OP 7 Allocs/OP BenchmarkUnmarshalWithPool-12 12662 95211 ns/op 232 B/op 6 allocs/op PASSCopy the code
BenchmarkUnmarshal took 94006 nanoseconds per cycle,
Results the item | meaning |
---|---|
BenchmarkUnmarshal-12 | BenchmarkUnmarshalIs the name of the function being tested– 12Indicates that the value of GOMAXPROCS (number of threads) is 12 |
13280 | That means all of them have been executed13280Time, that is,b.NThe value of the |
94006.0 ns/op | Represents the average cost per operation94006.0 nanoseconds |
1384/op | Indicates that each operation is applied1384 ByteMemory allocation for |
7 allocs/op | Indicates that each operation is applied7Time memory |
You can see that after sync.Pool is used, the memory usage is only 232/1384 unused.
The resources
- Geektutu.com/post/hpg-sy…
- Geektutu.com/post/high-p…
- Github.com/wangxiaomin…
- Geektutu.com/post/qa-gol…