sync.Pool比使用channel慢得多,那么为什么要使用sync.Pool? [英] sync.Pool is much slower than using channel, so why should we use sync.Pool?

查看:255
本文介绍了sync.Pool比使用channel慢得多,那么为什么要使用sync.Pool?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读了sync.Pool设计,但是发现它是两个逻辑,为什么我们需要localPool来解决锁竞争.我们可以使用chan来实现.

I read sync.Pool design, but find it is two logic, why we need localPool to solve lock compete. We can just use chan to implement one.

使用频道的速度是sync.pool的4倍!

Using channel is 4x times faster than sync.pool!

除了池可以清除对象外,它还有什么优势?

Besides pool can clear object, what advantage does it have?

这是池的实现和基准测试代码:

This is the pool implementation and benchmarking code:

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)
        }
    }
}

推荐答案

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

You are not benchmarking the same thing, so you can't compare the results.

BenchmarkName()启动的goroutines被窃听,您甚至不必等待这些goroutine完成,而BenchmarkNotPool()只是在同一个goroutine中获取对象并将其放入池中.

BenchmarkName() launches goroutines which have significant overheard and you don't even wait for those goroutines to finish, while BenchmarkNotPool() just gets and puts an object in the pool in the same goroutine.

如果您修改BenchmarkName()以执行相同的操作,则基准测试结果实际上表明是另一种方式:sync.Pool的速度提高了3倍以上,这是事实,所以这就是它的使用/优势.

If you modify BenchmarkName() to do the same, the benchmark results actually show it's the other way: sync.Pool is more than 3 times faster, which is true, so that's its use / advantage.

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())
        }
    }
}

结果:

BenchmarkName-8           500000              2453 ns/op
BenchmarkNotPool-8        200000              7984 ns/op

另请参阅相关问题:如何在Golang

这篇关于sync.Pool比使用channel慢得多,那么为什么要使用sync.Pool?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆