sync.Pool
是来自Go 1.3版本加入的特性,可以被看做是存放可被重用的值的容器,这个容器具有以下特性:
1. 可自动伸缩
2. 高效
3. 并发安全
因此这个类设计的目的是用来保存和复用临时对象,以减少内存分配,降低CG压力,但是由于这个原因,所以它并不可靠,因此每次GC,都会首先清楚缓冲区,假如一个slice是存放在 Pool 中,而又没有其他地方引用,则会被当成垃圾清理掉,因此切勿用sync.Pool
创建socket连接.
通过sync.Pool的源码,可以看出Pool创建的时候是不能指定大小的,所有sync.Pool
的缓存对象数量是没有限制的,它只受限于内存大小.
通过Get方法获取到的值是任意的.如果一个临时对象池的Put方法未被调用过,且它的New字段也未曾被赋予一个非nil的函数值,那么它的Get方法返回的结果值就一定会是nil.
Get方法返回的不一定就是存在于池中的值.不过,如果这个结果值是池中的,那么在该方法返回它之前就一定会把它从池中删除掉.
一个例子:
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")
}
编译时,禁用编译优化:go build -gcflags="-l -N"
.