Pool
一般超过几百个字节后建议使用,否则可能会因为该机制带来更大的性能损耗,造成过渡优化。
package main
import (
"fmt"
"sync"
)
type Person struct {
Name string
}
func (p *Person) String() string {
return fmt.Sprintf("<%s(%p)>", p.Name, p)
}
func main() {
pool := &sync.Pool{
New: func() interface{} {
fmt.Println("Create a new person")
return new(Person)
},
}
p := pool.Get().(*Person)
p.Name = "Andy"
fmt.Printf("Got %v.\n", p)
pool.Put(p)
fmt.Printf("Got %v.\n", pool.Get().(*Person))
fmt.Printf("Got %v.\n", pool.Get().(*Person))
}
上述代码会输出如下内容。
Create a new person
Got <Andy(0xc000012d50)>.
Got <Andy(0xc000012d50)>.
Create a new person
Got <(0xc000012d80)>.
可以看到,第二次是直接使用之前申请的对象,而且没有将对象复位 (使用时也不要用此时间);当第三次申请时,会重新申请一个对象。
模块使用
在标准模块中也会使用 Pool
来缓存对象,例如 fmt
模块。
fmt.Printf()
|-fmt.Fprintf()
|-fmt.newPrinter()
| |-ppFree.Get() 从sync.Pool中获取对象,并初始化buf成员
|-pp.doPrintf()
|-io.Writer.Write()
|-pp.free()
|-ppFree.Put()
在 pp.free()
函数中,为了尽量保证缓存池中对象大小的均衡,如果其中的缓冲区超过了大小,那么就不再放回到缓冲池中。