- Get/Put func is unbalanced on P.
- Usually Get and Put are not fired on the same goroutine, which will result in a difference in the fired times of Get and Put on each P. The difference part will trigger the steal operation(using CAS).
- poolLocal.private has only one.
- Get/Put operations are very frequent. In most cases, Get/Put needs to operate poolLocal.shared (using CAS) instead of the lock-free poolLocal.private.
- Frequent GC.
- sync.Pool is designed to serve objects with a short life cycle, but we just want to reuse, don’t want frequent GC.
- Transform poolLocal.private into an array to increase the frequency of poolLocal.private use.
- Batch operation poolLocal.shared, reduce CAS calls.
- Allow No GC.
- A single object is too large.
- syncx.Pool permanently holds up to runtime.GOMAXPROC(0)*256 reusable objects.
- For example, under a 4-core docker, a 4KB object will cause about 4MB of memory usage.
- please evaluate it yourself.
benchmark |
sync ns/op |
syncx ns/op |
delta |
BenchmarkSyncPoolParallel-4(p=16) |
877 |
620 |
-29.30% |
BenchmarkSyncPoolParallel-4(p=1024) |
49385 |
33465 |
-32.24% |
BenchmarkSyncPoolParallel-4(p=4096) |
255671 |
149522 |
-41.52% |
var pool = &syncx.Pool{
New: func() interface{} {
return &struct{}
},
NoGC: true,
}
func getput() {
var obj = pool.Get().(*struct)
pool.Put(obj)
}