go的临时对象池--sync.Pool

作者: bigtom | 来源:发表于2017-03-07 16:13 被阅读6253次

    一个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
    

    上面代码的运行结果显示使用对象池很明显提升了性能

    扩展阅读

    墙裂推荐
    golang内存回收
    bytepool

    相关文章

      网友评论

      • 2ac9162b4ccf:我这结果快了1s
        $ go run main.go
        without pool 17 s
        with pool 16 s
      • 业余码农:我这显示慢了呢
      • 2655b34fcb76:我copy你最后的代码进行测试,使用pool反而慢了
        阿飞go:@Str0ng 哪里变慢了 快了将近7s左右
        casonli:@钱大炮 put回去了 使用pool确实变慢了 楼主知道为何吗
        1a0d46742565:没有put回去吧?

      本文标题:go的临时对象池--sync.Pool

      本文链接:https://www.haomeiwen.com/subject/vwxoettx.html