一個sync.Pool對象就是一組臨時對象的集合通熄。Pool是協(xié)程安全的更耻。
Pool用于存儲那些被分配了但是沒有被使用,而未來可能會使用的值罚渐,以減小垃圾回收的壓力却汉。一個比較好的例子是fmt包,fmt包總是需要使用一些[]byte之類的對象荷并,golang建立了一個臨時對象池合砂,存放著這些對象,如果需要使用一個[]byte璧坟,就去Pool里面拿既穆,如果拿不到就分配一份。
這比起不停生成新的[]byte雀鹃,用完了再等待gc回收來要高效得多幻工。
type buffer []byte
// pp是用于存儲printer狀態(tài)的一個結(jié)構(gòu)體
type pp struct {
buf buffer
arg interface{}
value reflect.Value
fmt fmt
reordered bool
goodArgNum bool
panicking bool
erroring bool
}
//一個pp的對象池
var ppFree = sync.Pool{
New: func() interface{} { return new(pp) },
}
// 分配一個新的pp或者拿一個緩存的。
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
p.erroring = false
p.fmt.init(&p.buf)
return p
}
sync.Pool有兩個公開的方法黎茎。一個是Get囊颅,另一個是Put。前者的功能是從池中獲取一個interface{}類型的值傅瞻,而后者的作用則是把一個interface{}類型的值放置于池中踢代。
最簡單的例子
// 一個[]byte的對象池,每個對象為一個[]byte
var bytePool = sync.Pool{
New: func() interface{} {
b := make([]byte, 1024)
return &b
},
}
func main() {
a := time.Now().Unix()
// 不使用對象池
for i := 0; i < 1000000000; i++{
obj := make([]byte,1024)
_ = obj
}
b := time.Now().Unix()
// 使用對象池
for i := 0; i < 1000000000; i++{
obj := bytePool.Get().(*[]byte)
_ = obj
bytePool.Put(obj)
}
c := time.Now().Unix()
fmt.Println("without pool ", b - a, "s")
fmt.Println("with pool ", c - b, "s")
}
// without pool 34 s
// with pool 24 s
上面代碼的運行結(jié)果顯示使用對象池很明顯提升了性能
擴展閱讀
墻裂推薦
golang內(nèi)存回收
bytepool