文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go编程库Sync.Pool用法示例详解

2022-12-15 12:03

关注

场景

go 如果频繁地创建、销毁对象(比如 http 服务的 json 对象,日志内容等),会对 GC 造成压力。比如下面的 Log 函数,在高并发情况下,需要频繁地创建和销毁 buffer。

func Log(w io.Writer, key, val string) {
	b := new(bytes.Buffer)
  // 按一定的格式打印日志,这一段不是重点
	b.WriteString(time.Now().UTC().Format(time.RFC3339))
	b.WriteByte(' ')
	b.WriteString(key)
	b.WriteByte('=')
	b.WriteString(val)
	b.WriteByte('\n')
	w.Write(b.Bytes())
}

这时候可以考虑复用这些 buffer。我们可以维护一个 buffer 的对象池,需要的时候从对象池拿 buffer,用完放回对象池。这时候就推荐使用 sync.Pool 了。

sync.Pool 维护着一组对象池,需要时从对象池拿对象,不需要放回对象池就可以了。它有这些特点:

用法

创建

初始化时指定 New 方法。sync.Pool 会通过 New 方法创建对象池的对象。一般返回一个指针。

// 从对象池里取 buffer 时,如果池里没 buffer了,则调用 New 创建一个新的。
var bufPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}

GET & PUT

通过 Get 获取对象池的对象。当使用完毕,通过 Put 把对象返回对象池。

  b := bufPool.Get().(*bytes.Buffer)  // 从对象池拿 buffer 对象
  // 操作对象,这个不重要
	b.Reset()
	b.WriteString(time.Now().UTC().Format(time.RFC3339))
  // 操作完放回对象池
	bufPool.Put(b)

优化 Log 函数

Log 函数可以使用 sync.Pool 的优化,代码如下:

var bufPool = sync.Pool{
	New: func() interface{} {
		return new(bytes.Buffer)
	},
}
func LogWithPool(w io.Writer, key, val string) {
  // 从对象池拿 buffer 
	b := bufPool.Get().(*bytes.Buffer)
	b.Reset()
  // 按一定的格式打印日志,这一段不是重点
	b.WriteString(time.Now().UTC().Format(time.RFC3339))
	b.WriteByte(' ')
	b.WriteString(key)
	b.WriteByte('=')
	b.WriteString(val)
	b.WriteByte('\n')
	w.Write(b.Bytes())
  // 放回对象池
	bufPool.Put(b)
}

性能测试

我们对两个函数进行性能测试

// 不使用 sync.Pool
func BenchmarkLog(b *testing.B) {
	writer := os.NewFile(0, os.DevNull)
	for n := 0; n < b.N; n++ {
		Log(writer, "path", "/search?a=flowers")
	}
}
// 使用 sync.Pool 复用
func BenchmarkLogWithPool(b *testing.B) {
	writer := os.NewFile(0, os.DevNull)
	for n := 0; n < b.N; n++ {
		LogWithPool(writer, "path", "/search?a=flowers")
	}
}

结果:

> go test -bench . -benchmem
goos: darwin
goarch: amd64
pkg: example/pool
cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz
BenchmarkLog-8                   1849365               635.0 ns/op           112 B/op          2 allocs/op
BenchmarkLogWithPool-8           1993304               614.4 ns/op            48 B/op          1 allocs/op
PASS
ok      example/pool    4.333s

相比之下,使用 Sync.Pool 和不使用的时候,内存的使用比为 48:112,优化效果还是挺明显的。

参考:

[1]. pkg.go.dev/sync#Pool

以上就是Go编程库Sync.Pool用法示例详解的详细内容,更多关于Go库Sync.Pool的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯