​sync.Pool 使用

简介: ​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.

相关文章
|
4月前
|
存储 缓存 安全
go sync.Pool 设计与实现
go sync.Pool 设计与实现
42 2
|
5月前
|
NoSQL Java Redis
Redis16-RedisTemplate快速入门,max -idle,min-idle,max-wait,用set的方法,opsForValue().set的方法
Redis16-RedisTemplate快速入门,max -idle,min-idle,max-wait,用set的方法,opsForValue().set的方法
|
7月前
|
JavaScript 数据安全/隐私保护
v-model和.sync的区别
v-model和.sync的区别
184 0
|
JavaScript
彻底理解sync的用法
彻底理解sync的用法
184 0
|
缓存 关系型数据库 MySQL
【MySQL】thread_cache_size=16,是干什么的?底层原理是什么?
【MySQL】thread_cache_size=16,是干什么的?底层原理是什么?
284 0
|
存储 缓存 Go
原来sync.Once还能这么用
原来sync.Once还能这么用
168 0
原来sync.Once还能这么用
|
SQL 关系型数据库 MySQL
MGR修改max_binlog_cache_size参数导致异常
MGR修改max_binlog_cache_size参数导致异常
170 0
MGR修改max_binlog_cache_size参数导致异常
|
程序员 Go
你真的了解 sync.Once 吗
你真的了解 sync.Once 吗
183 0
|
SQL 缓存 关系型数据库
MySQL Buffer pool里的change buffer是啥?
change buffer是一种特殊的数据结构,当这些页面不在缓冲池中时,这些高速缓存会将更改缓存到辅助索引页面。可能由INSERT,UPDATE或DELETE操作(DML)导致的缓冲更改将在以后通过其他的读取操作将页加载到缓冲池中时合并。
291 0
MySQL Buffer pool里的change buffer是啥?
|
安全 Java Go
sync
sync包有以下几个内容: (1)sync.Pool 临时对象池 (2)sync.Mutex 互斥锁 (3)sync.RWMutex 读写互斥锁 (4)sync.WaitGroup 组等待 (5)sync.Cond 条件等待 (6)sync.Once 单次执行 一、临时对象池 Pool可以用来存储临时对象,其实原理就是这个对象池指向对象变量,以防没有变量指向对象时,被GC所回收。
1428 0