专栏首页程序员财富自由之路Go 语言中的 sync.Pool 使用

Go 语言中的 sync.Pool 使用

前言

不知道是得罪了哪位企业主,或者哪位企业主想购买我的公众号,然后被我拒绝,举报说公众号名称“程序员开发者社区“ 与个人公众号定位不符合。企鹅也认为是名称有点误解, 于是我改个更高调的名字,和所有程序员开发者共勉,正式改名为“程序员财富自由之路”!!!!

sync.Pool 使用场景

保存和复用临时对象,减少内存分配,降低 GC 压力

例子

type Student struct {
 Name   string
 Age    int32
 Remark [1024]byte
}

var buf, _ = json.Marshal(Student{Name: "Geektutu", Age: 25})

func unmarsh() {
 stu := &Student{}
 json.Unmarshal(buf, stu)
}

json 反序列化在文本解析和网络通信过程中十分常见,当程序并发很高时,短时间内需要创建大量的临时变量,,这些对象分配在堆上,会给 GC 造成很大压力,严重影响程序性能。

sync.Pool 是可伸缩的,同时也是并发安全的,大小受限于内存大小。sync.Pool 用于存储那些被分配了但是没有被使用,但是未来可能被使用的值。这样可以不用再次分配内存,提高效率。

sync.Pool 是大小可伸缩的,高负载时会动态扩容,存放在池中对象不活跃会被自动清理。

如何使用

声明对象池

只要实现 New 函数即可,对象池中没有对象,那么会调用 New 函数创建

var studentPool = sync.Pool{
    New: func() interface{} { 
        return new(Student) 
    },
}

Get& Put

stu := studentPool.Get().(*Student)
json.Unmarshal(buf, stu)
studentPool.Put(stu)

  • Get() 用于从对象池中获取对象,因为返回值时 interface{} 因此需要值类型转换
  • Put() 则是在对象使用完之后放回对象池

struct 性能测试

package sync

import (
   "encoding/json"
   "sync"
   "testing"
)

type Student struct {
   Name   string
   Age    int32
   Remark [1024]byte
}

var studentPool = sync.Pool{New: func() interface{} {
   return new(Student)
}}

var buf, _ = json.Marshal(Student{Name: "Geektutu", Age: 25})

func BenchmarkUnmarshal(b *testing.B) {
   for n := 0; n < b.N; n++ {
      stu := &Student{}
      json.Unmarshal(buf, stu)
   }
}

func BenchmarkUnmarshalWithPool(b *testing.B) {
   for n := 0; n < b.N; n++ {
      stu := studentPool.Get().(*Student)
      json.Unmarshal(buf, stu)
      studentPool.Put(stu)
   }
}

执行命令

 go test -bench . -benchmem

执行结果如下:

goos: darwin
goarch: amd64
pkg: code.byted.org/wangmingming.hit/GoProject/main/gobase/sync
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkUnmarshal-12                      13280             94006 ns/op            1384 B/op          7 allocs/op
BenchmarkUnmarshalWithPool-12              12662             95211 ns/op             232 B/op          6 allocs/op
PASS

BenchmarkUnmarshal 每个循环用了 94006 纳秒,

结果项

含义

BenchmarkUnmarshal-12

BenchmarkUnmarshal 是测试的函数名 -12 表示GOMAXPROCS(线程数)的值为12

13280

表示一共执行了13280次,即b.N的值

94006.0 ns/op

表示平均每次操作花费了94006.0纳秒

1384/op

表示每次操作申请了1384 Byte的内存申请

7 allocs/op

表示每次操作申请了7次内存

可以看到 使用 sync.Pool 后,内存占用仅为未使用的 232/1384.

公众号:程序员财富自由之路

博客:CSDN 王小明

关注我们,了解更多

关注后:回复 “AI” 或者 “内推”, 有惊喜

参考资料

  • https://geektutu.com/post/hpg-sync-pool.html
  • https://geektutu.com/post/high-performance-go.html
  • https://github.com/wangxiaoming/high-performance-go
  • https://geektutu.com/post/qa-golang-2.html#Q5-%E7%AE%80%E8%BF%B0-Go-%E8%AF%AD%E8%A8%80GC-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6-%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86

本文分享自微信公众号 - 程序员财富自由之路(gh_016ffe40d550),作者:猿星人

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-08-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go sync.Pool 浅析

    sync.Pool 应该是 Go 里面明星级别的数据结构,有很多优秀的文章都在介绍这个结构,本篇文章简单剖析下 sync.Pool。不过说实话 sync.Poo...

    haohongfan
  • 使用Go语言,25秒读取16GB文件

    当今世界的任何计算机系统每天都会生成大量的日志或数据。随着系统的发展,将调试数据存储到数据库中是不可行的,因为它们是不可变的,并且只能用于分析和解决故障。所以大...

    子润先生
  • Go 语言中的零拷贝优化

    ? 点击蓝字,关注我们 ? 导言 splice pipe pool for splice pipe pool in HAProxy pipe pool in ...

    腾讯VTeam技术团队
  • 深度解密Go语言之sync.pool

    最近在工作中碰到了 GC 的问题:项目中大量重复地创建许多对象,造成 GC 的工作量巨大,CPU 频繁掉底。准备使用 sync.Pool 来缓存对象,减轻 GC...

    梦醒人间
  • Go 语言并发编程系列(十五)—— sync 包系列:sync.Pool

    前面我们已经陆续介绍了 sync 包提供的各种同步工具,比如互斥锁、条件变量、原子操作、多协程协作等,今天我们来看另外一种工具。

    学院君
  • Go语言sync包的应用详解

    在并发编程中同步原语也就是我们通常说的锁的主要作用是保证多个线程或者 goroutine在访问同一片内存时不会出现混乱的问题。Go语言的sync包提供了常见的并...

    KevinYan
  • go语言的官方包sync.Pool的实现原理和适用场景

    已经使用golang有一段时间,go的协程和gc垃圾回收特性的确会提高程序的开发效率。但是毕竟是一门新语言,如果对于它的机制不了解,用起来可能会蹦出各种潘多拉盒...

    李海彬
  • Go 并发编程 — 深入浅出 sync.Pool ,最全的使用姿势,最深刻的原理

    Go 并发相关库 sync 里面有一个有趣的 package Pool,sync.Pool 是个有趣的库,用很少的代码实现了很巧的功能。第一眼看到 Pool 这...

    KevinYan
  • 网易基于Filebeat的日志采集服务设计与实践

    云原生技术大潮已经来临,技术变革迫在眉睫。 在这股技术潮流之中,网易推出了 轻舟微服务平台,集成了微服务、Service Mesh、容器云、DevOps等组件...

    Spark学习技巧
  • C语言和go语言之间的交互 - C语言中使用go语言,使用的go语言又使用了c语言

    一、go语言中使用C语言 go代码中使用C代码,在go语言的函数块中,以注释的方式写入C代码,然后紧跟import “C” 即可在go代码中使用C函数 ? 代码...

    magicsoar
  • ​sync.Pool 使用

    json 反序列化在文本解析和网络通信过程中十分常见,当程序并发很高时,短时间内需要创建大量的临时变量,,这些对象分配在堆上,会给 GC 造成很大压力,严重影响...

    王小明_HIT
  • Golang 语言临时对象池 - sync.Pool

    sync.Pool 是 sync 包提供的一个数据类型,也称为临时对象池,它的值是用来存储一组可以独立访问的临时对象,它通过池化减少申请新对象,提升程序的性能。...

    frank.
  • 从Baa开发中总结Go语言性能渐进优化

    在Go生态已经有很多WEB框架,但感觉没有一个符合我们的想法,我们想要一个简洁高效的核心框架,提供路由,context,中间件和依赖注入,而且拒绝使用正则和反射...

    李海彬
  • 论Go语言中goroutine的使用

    go中的goroutine是go语言在语言级别支持并发的一种特性。初接触go的时候对go的goroutine的欢喜至极,实现并发简便到简直bt的地步。但是在项目...

    李海彬
  • 【Go 语言社区】Go语言 Cookie的使用

    首先看看Cookie的结构体 type Cookie struct { Name string Value string Path string // opt...

    李海彬
  • 聊聊gost的ObjectPool

    gost的ObjectPool定义了New及sync.Pool属性,它提供了Get、Put方法,同时还有NewObjectPool工程方法;New是一个func...

    codecraft
  • 在Go语言中使用JSON

    Encode 将一个对象编码成JSON数据,接受一个interface{}对象,返回[]byte和error: func Marshal(v interfac...

    李海彬
  • Go 语言中使用 Protocol Buffers

    当前流行微服务框架,gRPC和Protocol Buffers 是 Go 的微服务框架常用的框架。

    zhangyunfeiVir
  • 【Golang语言社区】 Go语言中使用 Protobuf

    安装 goprotobuf 1.从 https://github.com/google/protobuf/releases 获取 Protobuf 编译器 pr...

    李海彬

扫码关注云+社区

领取腾讯云代金券