sync.Pool
一個sync.Pool對象就是一組臨時對象的集合。Pool是協程安全的。Pool用于存儲那些被配置設定了但是沒有被使用,而未來可能會使用的值,以減小垃圾回收的壓力。我們可以把sync.Pool類型值看作是存放可被重複使用的值的容器。此類容器是自動伸縮的、高效的,同時也是并發安全的。
Pool定義
type Pool struct {
func (p *Pool) Get() interface{}
func (p *Pool) Put(x interface{})
New func() interface{}
}
sync.Pool 最常用的兩個函數Get/Put,對象池在Get的時候如果裡面沒有對象會傳回nil,是以我們需要New function來確定當對象池為空時,重新生成一個對象傳回,前者的功能是從池中擷取一個interface{}類型的值,而後者的作用則是把一個interface{}類型的值放置于池中。
Get/Put
var BufferPool = sync.Pool{
New: func() interface{} { return helper.UUIDBuild() },
}
func TestNewHttpWrap(t *testing.T) {
for {
tmp:=BufferPool.Get()
fmt.Println(tmp)
time.Sleep(time.Second)
}
}
--------------------------------------------------------------------
3ef869eb18534a7888e8295cdb97f24e
0503331e7361433eb16d4dc87942b770
c24d2e269bb94d798fbf11da6b1d2468
2ec763ee841a4571a204c2b9663279c1
7c34f977fa204a6ea15422e971756cf7
72a27faaea8147e9ab29389fe65cc3df
每次都調用Get取對象,但是不調用Put,則每次取的值都是新建立的
var BufferPool = sync.Pool{
New: func() interface{} { return helper.UUIDBuild() },
}
func TestNewHttpWrap(t *testing.T) {
for i:=0;;i++ {
tmp:=BufferPool.Get()
fmt.Println(tmp)
BufferPool.Put(tmp)
time.Sleep(time.Second)
}
}
----------------------------------------------------------------
e1ea52bd1a204f55889330d44d97de49
22c2a6f9d4784457a753ab5eccdb7bd7
e1ea52bd1a204f55889330d44d97de49
22c2a6f9d4784457a753ab5eccdb7bd7
e1ea52bd1a204f55889330d44d97de49
每次都調用Get取對象,用完後Put,則每次取的值就會是之前存在的,這樣就減少了建立新對象的操作
臨時的概念
對象池使用是較簡單的,但原生的sync.Pool有個較大的問題:我們不能自由控制Pool中元素的數量,放進Pool中的對象每次GC發生時都會被清理掉。這使得sync.Pool做簡單的對象池還可以,但做連接配接池就有點心有餘而力不足了,比如:在高并發的情景下一旦Pool中的連接配接被GC清理掉,那每次連接配接DB都需要重新三次握手建立連接配接,這個代價就較大了。
例子:
var BufferPool = sync.Pool{
New: func() interface{} { return helper.UUIDBuild() },
}
func TestNewHttpWrap(t *testing.T) {
for i:=0;;i++ {
tmp:=BufferPool.Get()
fmt.Println(tmp)
BufferPool.Put(tmp)
time.Sleep(time.Second)
//每10秒GC一次
if (i%10)==0 {
runtime.GC()
fmt.Println("GC")
}
}
}
---------------------------------------------------------
812a05e41b6748d09aad4ef2003b581e
06e9611162324089b9b08ada47d109e4
812a05e41b6748d09aad4ef2003b581e
06e9611162324089b9b08ada47d109e4
812a05e41b6748d09aad4ef2003b581e
GC
39dc10511e4043ff8b3ea9ed47464067 //GC之後812a05e41b6748d09aad4ef2003b581e已經不存在了
d4e34df336ea44479022f4b138b0a448
39dc10511e4043ff8b3ea9ed47464067
d4e34df336ea44479022f4b138b0a448
39dc10511e4043ff8b3ea9ed47464067
可以看到GC之前Pool中Get到的對象是之前建立的,一旦GC之後,Pool中對象全部清空了,Get時又重新建立了。