geektutu / blog

极客兔兔的博客,Coding Coding 创建有趣的开源项目。
https://geektutu.com
Apache License 2.0
166 stars 21 forks source link

Go sync.Pool | Go 语言高性能编程 | 极客兔兔 #121

Open geektutu opened 3 years ago

geektutu commented 3 years ago

https://geektutu.com/post/hpg-sync-pool.html

Go 语言/golang 高性能编程,Go 语言进阶教程,Go 语言高性能编程(high performance go)。Go 语言标准库中的 sync.Pool 可以建立对象池,复用已有对象,解决内存分配碎片化的问题,有效减轻垃圾回收的压力(Garbage Collection, GC),在特定场景下可以有效地降低内存占用,提升性能。最后介绍了 sync.Pool 的作用和用法。

lisgroup commented 3 years ago

3.2 bytes.Buffer

①看到 BenchmarkBuffer 测试方法没有添加 buf.Reset() 方法,测试加上效果还是 pool 的性能更好

func BenchmarkBuffer(b *testing.B) {
    for n := 0; n < b.N; n++ {
        var buf bytes.Buffer
        buf.Write(data)
    }
}

②特意测试了:如果都不使用 Reset buf 操作,反而 pool 的性能不如原始的了!

func BenchmarkBufferWithPool(b *testing.B) {
    for n := 0; n < b.N; n++ {
        buf := bufferPool.Get().(*bytes.Buffer)
        buf.Write(data)
        // buf.Reset()
        bufferPool.Put(buf)
    }
}
geektutu commented 3 years ago

@lisgroup 第一个问题,buf 每次都是新申请的,所以没有必要 Reset()

第二个问题,buf.Reset() 相当于时执行了 buf.Truncate(0),把 slice 的大小设置为 0,底层的 byte 数组没有释放,所以加上 buf.Reset() 时不会影响性能的。这里 buf.Reset() 是必须执行的,如果不执行,下次从 pool 中取出来再用时,就是在原来的 buf 上追加写了,会导致错误的结果。

ionling commented 2 years ago

我这里跑的 BenchmarkUnmarshal 和文中差距有点大, go version go1.16.6 darwin/amd64:

goos: darwin
goarch: amd64
pkg: bench
cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
BenchmarkUnmarshalWithoutPool-8          1596366               742.6 ns/op           240 B/op          6 allocs/op
BenchmarkUnmarshalWithPool-8            1000000000               0.0000072 ns/op               0 B/op          0 allocs/op
bwb0101 commented 2 years ago

这测试不是特别准确,pool的测试相当于在外部定义了个变量,然后一直用这一个变量,所以pool的测试应该用并发测试看节省的内存

EddieChan1993 commented 2 years ago
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
BenchmarkUnmarshal-12                      12528             95266 ns/op            1400 B/op          8 allocs/op
BenchmarkUnmarshalWithPool-12              12388             94105 ns/op            1423 B/op          8 allocs/op

同样的代码,性能并没有太大差别 go version go1.17 darwin/amd64