Mygin上下文之sync.Pool复用
sync.Pool 的作用
先看看官方文档怎样说的吧,我截取了官方文档的第一句。
// A Pool is a set of temporary objects that may be individually saved and retrieved.
.....
- 简单翻译一下的意思是:池是一组可以单独保存和检索的临时对象。既然可以单独保存和检索的临时对象,对于大量重复地创建许多对象,造成 GC 的工作量巨大。而mygin的模式是 责任链模式 ,因此满足使用 sync.Pool。
- 一个 Pool 可以安全地由多个 goroutine 同时使用。池的目的是缓存已分配但未使用的项目以供以后重用,从而减轻垃圾回收器的压力。
- sync.Pool 是可伸缩的,同时也是并发安全的,其大小仅受限于内存的大小。sync.Pool 用于存储那些被分配了但是没有被使用,而未来可能会使用的值。这样就可以不用再次经过内存分配,可直接复用已有对象,减轻 GC 的压力,从而提升系统的性能。
以上都是源于官方文档翻译的,文档中还提到fmt包中,打印也使用了sync.Pool,感兴趣的可以点进源码查看。
sync.Pool 使用
sync.Pool 的使用方式非常简单:
只需要实现New函数即可。对象池中没有对象时,将会调用New函数创建,我使用了mygin中的context
创建
var contextPool = sync.Pool{
New: func() interface{} {
return new(Context)
},
}
使用和归还
c := contextPool.Get().(*Context)
json.Marshal(c)
contextPool.Put(c)
测试
func BenchmarkUnmarshal(b *testing.B) {
for n := 0; n < b.N; n++ {
c := &Context{}
json.Marshal(c)
}
}
func BenchmarkUnmarshalWithPool(b *testing.B) {
for n := 0; n < b.N; n++ {
c := contextPool.Get().(*Context)
json.Marshal(c)
contextPool.Put(c)
}
}
测试结果:
go test -bench . -benchmem
goos: linux
goarch: amd64
pkg: github.com/scott-pb/mygin
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
BenchmarkUnmarshal-8 5888780 208.1 ns/op 144 B/op 2 allocs/op
BenchmarkUnmarshalWithPool-8 7261801 165.0 ns/op 48 B/op 1 allocs/op
PASS
ok github.com/scott-pb/mygin 2.808s
在这个例子中,可以看出,使用了 sync.Pool 后,内存占用仅为未使用的 48/144= 1/3,对 GC 的影响就很大了。执行速度也快了,当然不同的设备测试结果也会不同。
测试源码
我把测试源码放在了mygin中 mygin/context_test.go
mygin使用sync.Pool
修改mygin/engine.go
修改engine.go中实例化conetxt的部分具体在ServeHTTP 方法中
修改前
//实例化一个下上文
c := &Context{
Request: r,
Writer: w,
Params: params,
handlers: handlers,
index: -1,
}
修改后
//从pool中取
c := e.pool.Get().(*Context)
c.Request = r
c.Writer = w
c.Params = params
c.handlers = handlers
c.index = -1
// 执行处理函数链
c.Next()
//归还到pool中
e.pool.Put(c)
mygin测试
main方法代码如下
package main
import (
"fmt"
"github.com/scott-pb/mygin"
"net/http"
)
func main() {
r := mygin.Default()
group := r.Group("/api")
group.GET("/test", func(c *mygin.Context) {
c.String(http.StatusOK, "success!\n")
})
err := r.Run(":8088")
if err != nil {
fmt.Println(err)
}
}
curl测试
curl -i http://localhost:8088/api/test
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Thu, 01 Feb 2024 05:08:52 GMT
Content-Length: 9
success!
这样mygin的context上下文就加入了Pool池,对于高并发情况下的GC压力会减轻不少。我设计的上下文中内容很少,随着功能的增多,效果会更加明显。
Mygin上下文之sync.Pool复用的更多相关文章
- [Go] sync.Pool 的实现原理 和 适用场景
摘录一: Go 1.3 的 sync 包中加入一个新特性:Pool. 官方文档可以看这里 http://golang.org/pkg/sync/#Pool 这个类设计的目的是用来保存和复用临时对象,以 ...
- Golang 临时对象池 sync.Pool
Go 1.3 的sync包中加入一个新特性:Pool.官方文档可以看这里http://golang.org/pkg/sync/#Pool 这个类设计的目的是用来保存和复用临时对象,以减少内存分配,降低 ...
- 深度解密 Go 语言之 sync.Pool
最近在工作中碰到了 GC 的问题:项目中大量重复地创建许多对象,造成 GC 的工作量巨大,CPU 频繁掉底.准备使用 sync.Pool 来缓存对象,减轻 GC 的消耗.为了用起来更顺畅,我特地研究了 ...
- 多图详解Go的sync.Pool源码
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 Pool介绍 总所周知Go 是一个自动垃圾回收的编程语言 ...
- sync.Pool:提高Go语言程序性能的关键一步
1. 简介 本文将介绍 Go 语言中的 sync.Pool并发原语,包括sync.Pool的基本使用方法.使用注意事项等的内容.能够更好得使用sync.Pool来减少对象的重复创建,最大限度实现对象的 ...
- sync.Pool的使用
一定要搞明白sync.Pool的正确用法,避免出现以下问题: kline := this.pool.Get() defer this.pool.Put(kline) kline.UnMarshal(d ...
- 深入Golang之sync.Pool详解
我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用的性能,为了减少GC,golang提供了对象重用的机制,也就是sync.Pool对象池. sync.Pool ...
- go语言学习--go的临时对象池--sync.Pool
一个sync.Pool对象就是一组临时对象的集合.Pool是协程安全的. Pool用于存储那些被分配了但是没有被使用,而未来可能会使用的值,以减小垃圾回收的压力.一个比较好的例子是fmt包,fmt包总 ...
- golang sync.Pool包的使用和一些注意地方
package main; import ( "sync" "fmt" "net" "runtime" ) //sync ...
- sync.Pool 资源池
sync.Pool type Pool struct { // 可选参数New指定一个函数在Get方法可能返回nil时来生成一个值 // 该参数不能在调用Get方法时被修改 New func() in ...
随机推荐
- 深入理解 Serverless 计算的并发度
作者|西流(阿里云技术专家) 背景 2019 年 Berkeley 预测 Serverless 将取代 Serverful 计算[1],成为云计算的计算新范式.Serverless 为应用程序开发提供 ...
- 当 Rokid 遇上函数计算
作者:王彬(阿里云解决方案架构师).姚兰天(Rokid 技术专家).聂大鹏(阿里云高级技术专家) 公司背景和业务 Rokid 创立于2014年,是一家专注于人机交互技术的产品平台公司.Rokid 通过 ...
- S3C2440移植linux3.4.2内核之修改分区以及制作根文件系统
上一节S3C2440移植linux3.4.2内核之内核框架介绍及简单修改我们简单配置了内核,这节来根据继续修改内核. 启动内核 内核启动的打印信息如下图所示 可以看到内核有8个分区,而我们的u ...
- js根据对象数组中某一属性值,合并相同项,并对某一属性累加处理
https://www.cnblogs.com/mahao1993/p/13491430.html
- vue-li3结合vantUI框架实现国际化语言切换
vue-cli3结合vantUI框架实现国际化语言切换 https://blog.csdn.net/weixin_45045199/article/details/105838517?utm_medi ...
- Delete `␍`eslint(prettier/prettier)错误
最佳实践: 现在VScode,Notepad++编辑器都能够自动识别文件的换行符是LF还是CRLF. 如果你用的是windows,文件编码是UTF-8且包含中文,最好全局将autocrlf设置为fal ...
- 实现不限层级的Element的NavMenu
做管理后台开发的时候,需要用到Element的NavMenu组件,于是乎,翻开文档,大致是这样实现的. <el-menu> <el-menu-item index="1&q ...
- html5 video视频,本地环境好的,线上环境,不能播放
本地环境ok,发布到线上不能播放.之前看这个视频,把video放在public文件夹下的. 后来经过排查,video放public文件夹下,导致的.应该放assets里. 后来,和同事讨论,线上服务器 ...
- C++ 语法结构--堆
1.堆介绍 「堆 heap」是一种满足特定条件的完全二叉树,主要可分为图 8-1 所示的两种类型. 「大顶堆 max heap」:任意节点的值 其子节点的值. 「小顶堆 min heap」:任意节点的 ...
- [转帖]【TiDB】快速起步
1. 存储引擎的的功能 提供数据存储接口并持久化存储数据 2. LSM-tree 的特性 LSM-tree 结构本质上是一个用空间置换写入延迟,用顺序写入替换随机写入的数据结构 3. 数据库技术的发展 ...