对象池的实现原理分析

文章目录什么是对象池?有哪些场景需要使用对象池?fmt包的应用字符串拼接应用对象池的实现(go1.12)相关结构定义设计思想对象池中获取对象向对象池归还对象GC回收对象池对象池的升级(go1.13)结构的调整方法实现调整性能的提升参考资料什么是对象池?对象池从字面上来理解,就是一个能存储很多对象的池子。在Go里面,对象池是通过使用sync包里的Pool结构来实现的,对象池能提高内存复用,减少内...
摘要由CSDN通过智能技术生成

什么是对象池?

对象池从字面上来理解,就是一个能存储很多对象的池子。在Go里面,对象池是通过使用sync包里的Pool结构来实现的,对象池能提高内存复用,减少内存申请次数,甚至能降低CPU消耗,是高并发项目优化不可缺少的手法之一。

作者的解释如下:

// A Pool is a set of temporary objects that may be individually saved and
// retrieved.
//
// Any item stored in the Pool may be removed automatically at any time without
// notification. If the Pool holds the only reference when this happens, the
// item might be deallocated.
//
// A Pool is safe for use by multiple goroutines simultaneously.
//
// Pool’s purpose is to cache allocated but unused items for later reuse,
// relieving pressure on the garbage collector. That is, it makes it easy to
// build efficient, thread-safe free lists. However, it is not suitable for all
// free lists.

有哪些场景需要使用对象池?

在go源码里,作者对sync.Pool使用做了如下的建议:

// An appropriate use of a Pool is to manage a group of temporary items
// silently shared among and potentially reused by concurrent independent
// clients of a package. Pool provides a way to amortize allocation overhead
// across many clients.
//
// On the other hand, a free list maintained as part of a short-lived object is
// not a suitable use for a Pool, since the overhead does not amortize well in
// that scenario. It is more efficient to have such objects implement their own
// free list.
//
// A Pool must not be copied after first use.

fmt包的应用

fmt.Sprintf()
var ppFree = sync.Pool{
   
        New: func() interface{
   } {
    return new(pp) },
}

// newPrinter allocates a new pp struct or grabs a cached one.
func newPrinter() *pp {
   
        p := ppFree.Get().(*pp)
        p.panicking = false
        p.erroring = false
        p.wrapErrs = false
        p.fmt.init(&p.buf)
        return p
}
// free saves used pp structs in ppFree; avoids an allocation per invocation.
func (p *pp) free() {
   
        // Proper usage of a sync.Pool requires each entry to have approximately
        // the same memory cost. To obtain this property when the stored type
        // contains a variably-sized buffer, we add a hard limit on the maximum buffer
        // to place back in the pool.
        //
        // See https://golang.org/issue/23199
        if cap(p.buf) > 64<<10 {
   
                return
        }

        p.buf = p.buf[:0]
        p.arg = nil
        p.value = reflect.Value{
   }
        p.wrappedErr = nil
        ppFree.Put(p)
}

// Sprintf formats according to a format specifier and returns the resulting string.
func Sprintf(format string, a ...interface{
   }) string {
   
        p := newPrinter()
        p.doPrintf(format, a)
        s := string(p.buf)
        p.free()
        return s
}

字符串拼接应用


var bytePool = sync.Pool{
   
        New: func() interface{
   } {
   
                buf := make([]byte, 0, 4096)
                return buf
        },
}
var ch = make(ch []byte,1000)

func main(){
   
 go func(){
   
  for msg := range ch {
   
   fmt.Println("recv msg")
      msg = msg[:0]
      bytePool.Put(msg)
  }
 }
 ...
 for i:0;i<=100000;i++ {
   
  lineBuf := bytePool.Get().([]byte)
  lineBuf = append(lineBuf, topic)
  lineBuf = append(lineBuf, position)
  lineBuf = append(lineBuf, info)
  lineBuf = append(lineBuf, data)
  ch <- lineBuf
 }

 time.Sleep(5 * time.Minute)
}

对象池的实现(go1.12)

相关结构定义

Pool

type Pool struct {
   
        noCopy noCopy

        local     unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal       
        localSize uintptr        // size of the local array

        // New optionally specifies a function to generate
        // a value when Get would otherwise return nil.
        // It may not be changed concurrently with calls to Get.
        New func() interface{
   }
}
  • noCopy      防止copy
  • local           本地对象池
  • localSize    本地对象池的大小
  • New           生成对象的接口方法

poolLocal


type poolLocal struct {
   
        poolLocalInternal

        // Prevents false sharing on widespread platforms with
        // 128 mod (cache line size) = 0 .
        pad [128 - unsafe.Sizeof(poolLocalInternal{
   })%128
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值