自学内容网 自学内容网

go Sync.Pool

sync 包提供了一个强大且可复用的实例池,以减少 GC 压力。在使用该包之前,我们需要在使用池之前和之后对应用程序进行基准测试。这非常重要,因为如果不了解它内部的工作原理,可能会影响性能。

池的限制

type Small struct {
   a int
}

var pool = sync.Pool{
   New: func() interface{} { return new(Small) },
}

//go:noinline
func inc(s *Small) { s.a++ }

func BenchmarkWithoutPool(b *testing.B) {
   var s *Small
   for i := 0; i < b.N; i++ {
      for j := 0; j < 10000; j++ {
         s = &Small{ a: 1, }
         b.StopTimer(); inc(s); b.StartTimer()
      }
   }
}

func BenchmarkWithPool(b *testing.B) {
   var s *Small
   for i := 0; i < b.N; i++ {
      for j := 0; j < 10000; j++ {
         s = pool.Get().(*Small)
         s.a = 1
         b.StopTimer(); inc(s); b.StartTimer()
         pool.Put(s)
      }
   }
}

基准测试:

name           time/op        alloc/op        allocs/op
WithoutPool-8  3.02ms ± 1%    160kB ± 0%      1.05kB ± 1%
WithPool-8     1.36ms ± 6%   1.05kB ± 0%        3.00 ± 0%

由于循环有 10k 次迭代,因此不使用池的基准测试在堆上需要 10k 次内存分配,而使用了池的基准测试仅进行了 3 次分配。 这 3 次分配由池产生的,但却只分配了一个结构实例。目前看起来还不错;使用 sync.Pool 更快,消耗更少的内存。
但是,在一个真实的应用程序中,你的实例可能会被用于处理繁重的任务,并会做很多头部内存分配。在这种情况下,当内存增加时,将会触发 GC。我们还可以使用命令 runtime.GC() 来强制执行基准测试中的 GC 来模拟此行为:

name           time/op        alloc/op        allocs/op
WithoutPool-8  993ms ± 1%    249kB ± 2%      10.9k ± 0%
WithPool-8     1.03s ± 4%    10.6MB ± 0%     31.0k ± 0%

池的内部工作流程

func init() {
   runtime_registerPoolCleanup(poolCleanup)
}

他将注册一个在运行时清理 pool 对象的方法。GC 在文件 runtime/mgc.go 中将触发这个方法:

func gcStart(trigger gcTrigger) {
   [...]
   // 在开始 GC 前调用 clearpools
   clearpools()

这就解释了为什么在调用 GC 时性能较低。因为每次 GC 运行时都会清理 pool 对象(译者注:pool 对象的生存时间介于两次 GC 之间)。文档也告知我们:

存储在池中的任何内容都可以在不被通知的情况下随时自动删除

在这里插入图片描述
对于我们创建的每个 sync.Pool,go 生成一个连接到每个处理器(译者注:处理器即 Go 中调度模型 GMP 的 P,pool 里实际存储形式是 [P]poolLocal)的内部池 poolLocal。该结构由两个属性组成:private 和 shared。第一个只能由其所有者访问(push 和 pop 不需要任何锁),而 shared 属性可由任何其他处理器读取,并且需要并发安全。实际上,池不是简单的本地缓存,它可以被我们的应用程序中的任何 线程/goroutines 使用。
Go 的 1.13 版本将改进 shared 的访问,并且还将带来一个新的缓存,以解决 GC 和池清理相关的问题。


原文地址:https://blog.csdn.net/2401_82869454/article/details/140435760

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!