请教关于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

不固定大小的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里放了。


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

要回复问题请先登录注册