Go: 理解 Sync.Pool 的设计

watermelo · 2019-06-30 22:54:33
更多评论

有点尴尬,直接拷的代码,跑了下发现结果不一样

代码

package pool

import (
    "runtime"
    "sync"
    "testing"
)

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 < 100000; j++ {
            s = &Small{ a: 1, }
            b.StopTimer(); inc(s); b.StartTimer()
        }
        runtime.GC()
    }

}

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

结果

BenchmarkWithoutPool-8                30          42271560 ns/op         1600078 B/op     100000 allocs/op
BenchmarkWithPool-8                  100          20146449 ns/op            1090 B/op          5 allocs/op

1.12.6的Go,有趣有趣,姿势不正确还是不一定国外文章都对?

#1

大致比例是差不多的,也能看出WithPool能带来的提升,作者的那几个数据的单位他自己换算过可能单位存在一些错误。 这是这次跑的数据,跟你的也差不多。

goos: darwin
goarch: amd64
pkg: pooltest
BenchmarkWithoutPool-4                20          76755420 ns/op         1600004 B/op     100000 allocs/op
BenchmarkWithPool-4                   50          29498700 ns/op             600 B/op          4 allocs/op

和文章对比也就是

name           time/op        alloc/op        allocs/op
WithoutPool-8  3.02ms ± 1% (76.7ms)    160kB ± 0% (1600kB)     1.05kB ± 1% 
WithPool-8     1.36ms ± 6%(29.5ms)   1.05kB ± 0%  (0.6KB)      3.00 ± 0%

每次执行时间比 2:1,分配内存比1600:1,分配次数比 100000:4。

#3