请教关于sync.Pool相关问题

我们的业务场景是每次查询会创建一个`slice`,这个`slice`大小不固定。最早想到的优化是申请`slice`的时候`make`一个较大的初始值。后来发现还是得继续优化,就用`sync.Pool`试了一下。 var idsPool = sync.Pool{ New: func() interface{} { ids := make([]int64, 0, 20000) return &ids }, } func NewIds() []int64 { ids := idsPool.Get().(*[]int64) *ids = (*ids)[:0] idsPool.Put(ids) return *ids } 代码如上,压了一把效果不明显。是不是`slice`这种对象不适合这么用呢?
已邀请:

dada

赞同来自: mnhkahn kevin qiyin

不固定大小的slice不适合都放一个pool里,可以参考我在slab项目里的做法。

https://github.com/funny/slab

看下sync_pool.go里的逻辑。

su21

赞同来自: frank mnhkahn

我的话会考虑预先创建若干个 不同 size 的 Pool 。
比如 32 64 128 256 512 etc,覆盖掉常用情景,少数太大或者太小的 slice 就回退到 make 创建。

stevewang

赞同来自: mnhkahn

做了性能测试分析吗?
我比较怀疑创建slice会是瓶颈,如果不是瓶颈就没有必要优化。
目前`sync.Pool`的实现中,对象池中的临时对象会在下次GC时失效,而且实现也用到了原子操作、线程锁和调度切换,性能上会有一些损耗。

dada

赞同来自: mnhkahn

还有一个简单的做法是控制最大的cap值,从pool创建时,始终用这个最大cap值创建,当释放时,判断cap是否超过最大值,超过就往pool里放了。

这样可以减少小的零散的创建。

要回复问题请先登录注册