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 ...
随机推荐
- UVA 156 Ananagrams STL应用
https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&prob ...
- Educational Codeforces Round 110 (Rated for Div. 2) (AB签到,C题双指针,D题DP好题)
补题链接:Here 1535A. Fair Playoff 四名选手参加了季后赛.比赛按以下方案进行:第一名选手与第二名选手比赛,第三名选手与第四名选手比赛,然后两人中的获胜者进入决赛. 众所周知,在 ...
- Redis 内存优化在 vivo 的探索与实践
作者:vivo 互联网服务器团队- Tang Wenjian 一. 背景 使用过 Redis 的同学应该都知道,它基于键值对(key-value)的内存数据库,所有数据存放在内存中,内存在 Redis ...
- vivo 大规模特征存储实践
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/u1LrIBtY6wNVE9lzvKXWjA作者:黄伟锋 本文旨在介绍 vivo 内部的特征存储 ...
- 【调试】crash使用方法
crash简介 crash是redhat的工程师开发的,主要用来离线分析linux内核转存文件,它整合了gdb工具,功能非常强大.可以查看堆栈,dmesg日志,内核数据结构,反汇编等等. crash支 ...
- Kafka 社区KIP-405中文译文(分层存储)
原文链接:https://cwiki.apache.org/confluence/display/KAFKA/KIP-405%3A+Kafka+Tiered+Storage 译者:Kafka KIP- ...
- C#设计模式01——单例模式的三种写法
第一种 //在方法里new ,这里使用 双if-lock public class SingleFirst { private static SingleFirst _SingleFirst; pri ...
- python进度条实现的几种方法
一.普通进度条(time实现) import time def progress_bar(): for i in range(101): print(f'\rProgress: {"#&qu ...
- [转帖]Oracle如何重启mmon/mmnl进程(AWR自动采集)
https://www.cnblogs.com/jyzhao/p/10119854.html 学习一下 环境:Oracle 11.2.0.4 RAC现象:sysaux空间满导致无法正常生成快照,清理空 ...
- [转帖]Windows平台下使用 Rclone 挂载 OneDrive 为本地硬盘
https://zhuanlan.zhihu.com/p/139200172 Rclone (rsync for cloud storage) 是一个命令行程序,用于同步文件和目录,支持常见的 Ama ...