type Pool struct {
noCopy noCopy
local unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
localSize uintptr // size of the local array
victim unsafe.Pointer // local from previous cycle
victimSize uintptr // size of victims array
// New optionally specifies a function to generate
// a value when Get would otherwise return nil.
// It may not be changed concurrently with calls to Get.
New func() interface{}
}
// Local per-P Pool appendix.
type poolLocalInternal struct {
private interface{} // Can be used only by the respective P.
shared poolChain // Local P can pushHead/popHead; any P can popTail.
}
type poolLocal struct {
poolLocalInternal
// Prevents false sharing on widespread platforms with
// 128 mod (cache line size) = 0 .
pad [128 - unsafe.Sizeof(poolLocalInternal{})%128]byte
}
sync.Pool 的特性
- 池不能够指定大小,大小只受限于 GC 的临界值(GOMAXPROCS)
- 对象最大的缓存周期是两个 GC 周期,每次 GC ,当前的 primary cache 会被转移到 victim cache,primary cache 清空,而原来 victim cache 被释放
- 取值顺序:当前 P 的 primary cache(local)的 poolLocal.private → 当前 P 的 primary cache(local)的 poolLocal.shared.head → 其他 P 的主存(local)的 poolLocal.shared.tail → 当前 P 的 victim cache(victim) 的 poolLocal.private → 当前 P 的 victim cache(victim) 的 poolLocal.shared.head → 其他 P 的主存(local)的 poolLocal.shared.tail → p.New() → nil
- 插入顺序:当前 P 的 primary cache(local)的 poolLocal.private → 当前 P 的 primary cache(local)的 poolLocal.shared.head
sync.pool拿取缓存的过程
-
一个goroutine会抢占p,然后首先从当前p的private 中选择对象,如果里面没找到,然后尝试本地p的shared 队列的队头进行读取,若还是取不到,则尝试从其他 P 的 shared 队列队尾中偷取。 若偷不到,则尝试从上一个 GC 周期遗留到 victim 缓存中取,否则调用 New 创建一个新的对象。
-
对于回收而言,池中所有临时对象在一次 GC 后会被放入 victim 缓存中, 而前一个周期被放入 victim 的缓存则会被清理掉。
-
在加入 victim 机制前,sync.Pool 里对象的最⼤缓存时间是一个 GC 周期,当 GC 开始时,没有被引⽤的对象都会被清理掉;加入 victim 机制后,最大缓存时间为两个 GC 周期。
-
当get一个对象使用完成之后,调用put归还的时候,需要注意将里面的内容清除
-
Pool 不可以指定⼤⼩,⼤⼩只受制于 GC 临界值。
网友评论