sync.Pool比使用channel慢得多,那么为什么要使用sync.Pool?

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)

icz*_*cza 5

您不是对同一事物进行基准测试,因此无法比较结果。

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中实现内存池