​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.

相关文章
|
JavaScript 前端开发 Shell
如何正确使用淘宝npm镜像
如何正确使用淘宝npm镜像
2462 0
如何正确使用淘宝npm镜像
|
前端开发 JavaScript NoSQL
全球排名前 3 的开源低代码开发平台测评
低代码开发平台一般内置多种前端 UI 组件,包括表格、表单、图表、富文本编辑器、时间选择器、下拉菜单、地图等,几乎所有搭建工具时需要的前端组件,都能在低代码开发平台内找到。也就是说,你在根据自己需求搭建工具的过程中,完全不需要写任何前端代码,仅需拖拽即可瞬间生成前端组件,后端数据库及 API 也帮你一键连入,简单几行代码,轻松搭建工具。比如可快速构建 admin 后台管理 、销售 ERP、客户 CRM、数据分析看板、云端文件上传管理等基于数据库或 API 的管理工具,曾经用 Vue 开发需要数周,现在只需要几小时,极大提高了开发效率。谁用谁知道,早用早下班。
4320 0
|
7月前
|
SQL 关系型数据库 MySQL
【MySQL】SQL分析的几种方法
以上就是SQL分析的几种方法。需要注意的是,这些方法并不是孤立的,而是相互关联的。在实际的SQL分析中,我们通常需要结合使用这些方法,才能找出最佳的优化策略。同时,SQL分析也需要对数据库管理系统,数据,业务需求有深入的理解,这需要时间和经验的积累。
264 12
|
存储 前端开发 JavaScript
前端技术深度探索:从基础到现代框架的实践之旅
前端技术深度探索:从基础到现代框架的实践之旅
242 3
|
运维 Linux Apache
【一键变身超人!】Puppet 自动化运维神器 —— 让你的服务器听话如婴儿,轻松管理资源不是梦!
【8月更文挑战第9天】随着云计算与容器化技术的发展,自动化运维已成为现代IT基础设施的核心部分。Puppet是一款强大的自动化工具,用于配置管理,确保系统保持预期状态。通过易于理解的配置文件定义资源及其依赖关系,Puppet实现了“基础设施即代码”的理念。本文简要介绍了Puppet的安装配置方法及示例,包括Puppet Agent与Master的安装、基本配置步骤和一个简单的Apache HTTP Server管理示例,展示了Puppet在实际应用中的强大功能与灵活性。
235 9
|
缓存 安全 Java
Spring高手之路21——深入剖析Spring AOP代理对象的创建
本文详细介绍了Spring AOP代理对象的创建过程,分为三个核心步骤:判断是否增强、匹配增强器和创建代理对象。通过源码分析和时序图展示,深入剖析了Spring AOP的工作原理,帮助读者全面理解Spring AOP代理对象的生成机制及其实现细节。
467 0
Spring高手之路21——深入剖析Spring AOP代理对象的创建
|
监控 前端开发 Java
深入理解 org.springframework.web.servlet.AsyncHandlerInterceptor
深入理解 org.springframework.web.servlet.AsyncHandlerInterceptor
284 0
|
安全 Linux 网络安全
2024黑龙江省职业院校技能大赛信息安全管理与评估赛项规程
2024黑龙江省职业院校技能大赛信息安全管理与评估赛项规程
|
存储 程序员 Shell
【C/C++ 内存管理函数】C语言动态内存管理大揭秘:malloc、calloc、realloc与new的对比与差异
【C/C++ 内存管理函数】C语言动态内存管理大揭秘:malloc、calloc、realloc与new的对比与差异
605 0
|
消息中间件 小程序 Java
暹罗点餐开源啦,一款java多门店点餐系统-连锁门店如蜜雪冰城瑞幸咖啡
暹罗点餐是一款Java餐饮点餐系统,适用于多门店的连锁品牌,对标蜜雪冰城、瑞幸咖啡。系统包含用户端、商家端、配送端以及总管理后台; * 前端使用uni-app开发,可打包部署到微信小程序、APP、H5 * Web端使用vue + Element开发 * 服务端使用java语言开发,技术栈:Spring Boot + Redis + RocketMQ + WebSocket + ElasticSearch + ELK + SpringBoot Admin
1043 1
暹罗点餐开源啦,一款java多门店点餐系统-连锁门店如蜜雪冰城瑞幸咖啡