Skip to main content
 首页 » 编程设计

go语言学习--go的临时对象池--sync.Pool

2022年07月19日130lautakyan007
一个sync.Pool对象就是一组临时对象的集合。Pool是协程安全的。
Pool用于存储那些被分配了但是没有被使用,而未来可能会使用的值,以减小垃圾回收的压力。一个比较好的例子是fmt包,fmt包总是需要使用一些[]byte之类的对象,golang建立了一个临时对象池,存放着这些对象,如果需要使用一个[]byte,就去Pool里面拿,如果拿不到就分配一份。
这比起不停生成新的[]byte,用完了再等待gc回收来要高效得多。
type buffer []byte 
// pp是用于存储printer状态的一个结构体 
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

我们可以明显的看出使用了对象池速度有了明显的提升


本文参考链接:https://www.cnblogs.com/ricklz/p/9865079.html
阅读延展