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复用的更多相关文章

  1. [Go] sync.Pool 的实现原理 和 适用场景

    摘录一: Go 1.3 的 sync 包中加入一个新特性:Pool. 官方文档可以看这里 http://golang.org/pkg/sync/#Pool 这个类设计的目的是用来保存和复用临时对象,以 ...

  2. Golang 临时对象池 sync.Pool

    Go 1.3 的sync包中加入一个新特性:Pool.官方文档可以看这里http://golang.org/pkg/sync/#Pool 这个类设计的目的是用来保存和复用临时对象,以减少内存分配,降低 ...

  3. 深度解密 Go 语言之 sync.Pool

    最近在工作中碰到了 GC 的问题:项目中大量重复地创建许多对象,造成 GC 的工作量巨大,CPU 频繁掉底.准备使用 sync.Pool 来缓存对象,减轻 GC 的消耗.为了用起来更顺畅,我特地研究了 ...

  4. 多图详解Go的sync.Pool源码

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 Pool介绍 总所周知Go 是一个自动垃圾回收的编程语言 ...

  5. sync.Pool:提高Go语言程序性能的关键一步

    1. 简介 本文将介绍 Go 语言中的 sync.Pool并发原语,包括sync.Pool的基本使用方法.使用注意事项等的内容.能够更好得使用sync.Pool来减少对象的重复创建,最大限度实现对象的 ...

  6. sync.Pool的使用

    一定要搞明白sync.Pool的正确用法,避免出现以下问题: kline := this.pool.Get() defer this.pool.Put(kline) kline.UnMarshal(d ...

  7. 深入Golang之sync.Pool详解

    我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用的性能,为了减少GC,golang提供了对象重用的机制,也就是sync.Pool对象池. sync.Pool ...

  8. go语言学习--go的临时对象池--sync.Pool

    一个sync.Pool对象就是一组临时对象的集合.Pool是协程安全的. Pool用于存储那些被分配了但是没有被使用,而未来可能会使用的值,以减小垃圾回收的压力.一个比较好的例子是fmt包,fmt包总 ...

  9. golang sync.Pool包的使用和一些注意地方

    package main; import ( "sync" "fmt" "net" "runtime" ) //sync ...

  10. sync.Pool 资源池

    sync.Pool type Pool struct { // 可选参数New指定一个函数在Get方法可能返回nil时来生成一个值 // 该参数不能在调用Get方法时被修改 New func() in ...

随机推荐

  1. freeswitch的任务引擎问题与解决方案

    概述 freeswitch核心框架中有一个定时任务系统task,在开发过程中用来做一些延时操作和异步操作很方便. 我们在VOIP的呼叫流程中,经常会有一些对实时性要求没那么高的操作,或者会有阻塞流程的 ...

  2. C#查找算法2:插值查找

    插值查找,有序表的一种查找方式.插值查找是根据查找关键字与查找表中最大最小记录关键字比较后的查找方法.插值查找基于二分查找,将查找点的选择改进为自适应选择,提高查找效率. 原理:    (midInd ...

  3. Liunx常用操作(11)-VI编辑器-末行模式命令

    vI编辑器三种模式 分别为命令模式.输入模式.末行模式.

  4. spring boot 中默认最大线程连接数,线程池数配置查看

    本文为博主原创,转载请注明出处: 可以查看 AbstractEndpoint  源码中的常量的定义: public abstract class AbstractEndpoint<S, U> ...

  5. Pgsql之查询一段时间内的所有日期

    前几天干活儿的时候,项目中有这么个需求,需要用pgsql查询两个日期间的所有日期,包括年月日,下面贴代码: 1 select date(t) as day 2 from 3 generate_seri ...

  6. JS逆向实战27——pdd的anti_content 分析与逆向

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 本文已在微信公众号发布 目 ...

  7. [转帖]解Bug之路-NAT引发的性能瓶颈

    https://zhuanlan.zhihu.com/p/286532997 解Bug之路-NAT引发的性能瓶颈 笔者最近解决了一个非常曲折的问题,从抓包开始一路排查到不同内核版本间的细微差异,最后才 ...

  8. [转帖]下载 SQL Server Management Studio (SSMS)

    https://learn.microsoft.com/zh-CN/sql/ssms/download-sql-server-management-studio-ssms?view=sql-serve ...

  9. Python学习之十四_Python连接各种数据库的方法(DM,oscar,Oracle,SQLSERVER,MYSQL,PG,Kingbase

    Python学习之十四_Python连接各种数据库的方法(DM,oscar,Oracle,SQLSERVER,MYSQL,PG,Kingbase) 前言 想着能够使用多种数据库进行一些操作. 所以本文 ...

  10. [转帖]FIO磁盘性能测试工具

    https://www.cnblogs.com/lyhabc/p/16708771.html 简介 一般我们测试硬盘或者存储的性能的时候,会用Linux系统自带的dd命令,因为是自带命令,简单易使用, ...