pet*_*lin 0 benchmarking synchronization pool channel go
我读了sync.Pool设计,但发现有两种逻辑,为什么我们需要localPool来解决锁竞争。我们可以使用chan来实现一个。
使用频道的速度是的4倍sync.pool!
除了池可以清除对象外,它还有什么优势?
这是池实现和基准测试代码:
package client
import (
"runtime"
"sync"
"testing"
)
type MPool chan interface{}
type A struct {
s string
b int
overflow *[2]*[]*string
}
var p = sync.Pool{
New: func() interface{} { return new(A) },
}
var mp MPool = make(chan interface{}, 100)
func get() interface{} {
select {
case r := <-mp:
return r
default:
return new(A)
}
}
func put(a interface{}) {
select {
case mp <- a:
default:
}
return
}
func pool() {
a := p.Get()
p.Put(a)
}
func init() {
runtime.GOMAXPROCS(8)
}
func BenchmarkName(b *testing.B) {
for i := 0; i < 20; i++ {
p.Put(new(A))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i := 0; i < 100; i++ {
go func() {
p.Put(p.Get())
}()
}
}
}
func BenchmarkNotPool(b *testing.B) {
for i := 0; i < 20; i++ {
put(new(A))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i := 0; i < 100; i++ {
a := get()
put(a)
}
}
}
Run Code Online (Sandbox Code Playgroud)
您不是对同一事物进行基准测试,因此无法比较结果。
BenchmarkName()会启动一个被大量窃听的goroutine,您甚至不必等待这些goroutine完成,而BenchmarkNotPool()只需在同一个goroutine中将对象放入并放入池中即可。
如果您进行修改BenchmarkName()以执行相同的操作,则基准测试结果实际上表明它是另一种方式:sync.Pool速度提高了3倍以上,这是事实,因此这就是它的使用/优点。
func BenchmarkName(b *testing.B) {
for i := 0; i < 20; i++ {
p.Put(new(A))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i := 0; i < 100; i++ {
p.Put(p.Get())
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
BenchmarkName-8 500000 2453 ns/op
BenchmarkNotPool-8 200000 7984 ns/op
Run Code Online (Sandbox Code Playgroud)
另请参阅相关问题:如何在Golang中实现内存池