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.


相关文章
|
8天前
|
存储 前端开发 Go
Go语言中的数组
在 Go 语言中,数组是一种固定长度的、相同类型元素的序列。数组声明时长度已确定,不可改变,支持多种初始化方式,如使用 `var` 关键字、短变量声明、省略号 `...` 推断长度等。数组内存布局连续,可通过索引高效访问。遍历数组常用 `for` 循环和 `range` 关键字。
|
9天前
|
Go 调度 开发者
Go语言中的并发编程:深入理解与实践###
探索Go语言在并发编程中的独特优势,揭秘其高效实现的底层机制。本文通过实例和分析,引导读者从基础到进阶,掌握Goroutines、Channels等核心概念,提升并发处理能力。 ###
|
5天前
|
存储 安全 算法
Go语言是如何支持多线程的
【10月更文挑战第21】Go语言是如何支持多线程的
101 72
|
5天前
|
安全 大数据 Go
介绍一下Go语言的并发模型
【10月更文挑战第21】介绍一下Go语言的并发模型
24 14
|
1天前
|
编译器 Go
go语言编译选项
【10月更文挑战第17天】
9 5
|
4天前
|
安全 Go 开发者
go语言并发模型
【10月更文挑战第16天】
18 8
|
1天前
|
缓存 安全 Java
go语言 代码优化
【10月更文挑战第17天】
11 4
|
1天前
|
设计模式 测试技术 Go
学习Go语言
【10月更文挑战第25天】学习Go语言
12 4
|
1天前
|
缓存 监控 算法
go语言
【10月更文挑战第25天】go语言
8 4
|
1天前
|
Java 程序员 Go
Go语言的开发
【10月更文挑战第25天】Go语言的开发
9 3